How to use compound key for dictionary? - c#

I need to arrange sort of dictionary where the key would be a pair of enum and int
and value is object. So I want to map a pair to some object.
One option would be
public enum SomeEnum
{
value1, value2
}
class Key
{
public SomeEnum;
public int counter;
// Do I have to implement Compare here?
}
Dictionary<SomeEnum, object> _myDictionary;
Another option would convert enum and int to some unique key.
string key = String.Format("{0}/{1}", enumValue, intValue)
That approach requires string parsing, a lot of extra work.
How to make it easily?

I would go with something similar to
public enum SomeEnum
{
value1, value2
}
public struct Key
{
public SomeEnum;
public int counter;
}
Dictionary<Key, object>
I think that would make it?

If you are going to put this in a dictionary, then you will need to make sure you implement a meaningful .Equals and .GetHashCode or the dictionary will not behave correctly.
I'd start off with something like the following for the basic compound key, and then implement a custom IComparer to get the sort order you need.
public class MyKey
{
private readonly SomeEnum enumeration;
private readonly int number;
public MyKey(SomeEnum enumeration, int number)
{
this.enumeration = enumeration;
this.number = number;
}
public int Number
{
get { return number; }
}
public SomeEnum Enumeration
{
get { return enumeration; }
}
public override int GetHashCode()
{
int hash = 23 * 37 + this.enumeration.GetHashCode();
hash = hash * 37 + this.number.GetHashCode();
return hash;
}
public override bool Equals(object obj)
{
var supplied = obj as MyKey;
if (supplied == null)
{
return false;
}
if (supplied.enumeration != this.enumeration)
{
return false;
}
if (supplied.number != this.number)
{
return false;
}
return true;
}
}

If you are using C# 4.0, you could use the Tuple class.
var key = Tuple.Create(SomeEnum.Value1, 3);

Related

Get HashCode from object [duplicate]

I'm looking at how build the best HashCode for a class and I see some algorithms. I saw this one : Hash Code implementation, seems to be that .NET classes HashCode methods are similar (see by reflecting the code).
So question is, why don't create the above static class in order to build a HashCode automatically, just by passing fields we consider as a "key".
// Old version, see edit
public static class HashCodeBuilder
{
public static int Hash(params object[] keys)
{
if (object.ReferenceEquals(keys, null))
{
return 0;
}
int num = 42;
checked
{
for (int i = 0, length = keys.Length; i < length; i++)
{
num += 37;
if (object.ReferenceEquals(keys[i], null))
{ }
else if (keys[i].GetType().IsArray)
{
foreach (var item in (IEnumerable)keys[i])
{
num += Hash(item);
}
}
else
{
num += keys[i].GetHashCode();
}
}
}
return num;
}
}
And use it as like this :
// Old version, see edit
public sealed class A : IEquatable<A>
{
public A()
{ }
public string Key1 { get; set; }
public string Key2 { get; set; }
public string Value { get; set; }
public override bool Equals(object obj)
{
return this.Equals(obj as A);
}
public bool Equals(A other)
{
if(object.ReferenceEquals(other, null))
? false
: Key1 == other.Key1 && Key2 == other.Key2;
}
public override int GetHashCode()
{
return HashCodeBuilder.Hash(Key1, Key2);
}
}
Will be much simpler that always is own method, no? I'm missing something?
EDIT
According all remarks, I got the following code :
public static class HashCodeBuilder
{
public static int Hash(params object[] args)
{
if (args == null)
{
return 0;
}
int num = 42;
unchecked
{
foreach(var item in args)
{
if (ReferenceEquals(item, null))
{ }
else if (item.GetType().IsArray)
{
foreach (var subItem in (IEnumerable)item)
{
num = num * 37 + Hash(subItem);
}
}
else
{
num = num * 37 + item.GetHashCode();
}
}
}
return num;
}
}
public sealed class A : IEquatable<A>
{
public A()
{ }
public string Key1 { get; set; }
public string Key2 { get; set; }
public string Value { get; set; }
public override bool Equals(object obj)
{
return this.Equals(obj as A);
}
public bool Equals(A other)
{
if(ReferenceEquals(other, null))
{
return false;
}
else if(ReferenceEquals(this, other))
{
return true;
}
return Key1 == other.Key1
&& Key2 == other.Key2;
}
public override int GetHashCode()
{
return HashCodeBuilder.Hash(Key1, Key2);
}
}
Your Equals method is broken - it's assuming that two objects with the same hash code are necessarily equal. That's simply not the case.
Your hash code method looked okay at a quick glance, but could actually do some with some work - see below. It means boxing any value type values and creating an array any time you call it, but other than that it's okay (as SLaks pointed out, there are some issues around the collection handling). You might want to consider writing some generic overloads which would avoid those performance penalties for common cases (1, 2, 3 or 4 arguments, perhaps). You might also want to use a foreach loop instead of a plain for loop, just to be idiomatic.
You could do the same sort of thing for equality, but it would be slightly harder and messier.
EDIT: For the hash code itself, you're only ever adding values. I suspect you were trying to do this sort of thing:
int hash = 17;
hash = hash * 31 + firstValue.GetHashCode();
hash = hash * 31 + secondValue.GetHashCode();
hash = hash * 31 + thirdValue.GetHashCode();
return hash;
But that multiplies the hash by 31, it doesn't add 31. Currently your hash code will always return the same for the same values, whether or not they're in the same order, which isn't ideal.
EDIT: It seems there's some confusion over what hash codes are used for. I suggest that anyone who isn't sure reads the documentation for Object.GetHashCode and then Eric Lippert's blog post about hashing and equality.
This is what I'm using:
public static class ObjectExtensions
{
/// <summary>
/// Simplifies correctly calculating hash codes based upon
/// Jon Skeet's answer here
/// http://stackoverflow.com/a/263416
/// </summary>
/// <param name="obj"></param>
/// <param name="memberThunks">Thunks that return all the members upon which
/// the hash code should depend.</param>
/// <returns></returns>
public static int CalculateHashCode(this object obj, params Func<object>[] memberThunks)
{
// Overflow is okay; just wrap around
unchecked
{
int hash = 5;
foreach (var member in memberThunks)
hash = hash * 29 + member().GetHashCode();
return hash;
}
}
}
Example usage:
public class Exhibit
{
public virtual Document Document { get; set; }
public virtual ExhibitType ExhibitType { get; set; }
#region System.Object
public override bool Equals(object obj)
{
return Equals(obj as Exhibit);
}
public bool Equals(Exhibit other)
{
return other != null &&
Document.Equals(other.Document) &&
ExhibitType.Equals(other.ExhibitType);
}
public override int GetHashCode()
{
return this.CalculateHashCode(
() => Document,
() => ExhibitType);
}
#endregion
}
Instead of calling keys[i].GetType().IsArray, you should try to cast it to IEnumerable (using the as keyword).
You can fix the Equals method without repeating the field list by registering a static list of fields, like I do here using a collection of delegates.
This also avoids the array allocation per-call.
Note, however, that my code doesn't handle collection properties.

how to create a custom cast explicit in c #?

Have this code:
string abc = "123456";
To convert to int should I use convert:
int abcInt = Convert.ToInt32(abc);
The problem is that if not a number I have an exception see returning zero so my final code will look like:
try{ int abcInt = Convert.ToInt32(abc); }catch(Exception e){ int abcInt = 0; }
So you see that I decided to create a book that made ​​me an object returning zero numeric without exception if it failed, so could keep most flexible programming without much junk code:
int abcInt = Libs.str.safeInt(abc);
The code is:
public int safeInt(object ob)
{
if ((ob == null) || (String.IsNullOrEmpty(ob.ToString())))
return 0;
try
{
return Convert.ToInt32(
System.Text.RegularExpressions.Regex.Replace(ob.ToString(), #"#[^Ee0-9\.\,]+#i", "").
ToString(CultureInfo.InvariantCulture.NumberFormat)
);
}
catch (FormatException e)
{
return 0;
}
}
But I want to go one step further and do something like this:
int abcInt = (safeInt)abc;
how to do?
Can not convert type 'string' to 'Libs.safeInt.safeInt'
You should just use Int32.TryParse:
int abcInt;
if(!Int32.TryParse(abc, out abcInt)) {
abcInt = 0;
}
// abcInt has been parsed to an int, or defaulted to zero
Note that this can be shortened to
int abcInt;
Int32.TryParse(abc, out abcInt);
if all that you want is the default value to be zero because:
When this method returns, contains the 32-bit signed integer value equivalent to the number contained in s, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the s parameter is null, is not of the correct format, or represents a number less than MinValue or greater than MaxValue. This parameter is passed uninitialized.
I actually recommend against writing it this way because now you can't distinguish between abc = "0" and abc = "garbage"; both with exhibit exactly the same behavior with the above two lines of code. With the initial version above (i.e., the if, you can distinguish the two cases if you need to; silently ignoring errors is generally a bad idea).
That said, if you absolutely are dying to know how to implement an explicit cast operator, you proceed like this:
class SafeInt32 {
private readonly int value;
public int Value { get { return this.value; } }
private readonly string source;
public string Source { get { return this.source; } }
private readonly bool successful;
public bool Successful { get { return this.successful; } }
public SafeInt32(string source) {
this.source = source;
this.successful = Int32.TryParse(source, out this.value);
}
public static explicit operator SafeInt32(string source) {
return new SafeInt32(source);
}
public static implicit operator int(SafeInt32 safeInt32) {
return safeInt32.Value;
}
}
Usage:
int abcInt = (SafeInt32)"123456";
Note that we had to define an explicit cast operator to cast a string to a SafeInt32, and an implicit cast operator to cast a SafeInt32 to an int to achieve your desired syntax. The latter is necessary so that the compiler can silently convert the result of (SafeInt32)"123456" to an int.
Again, I recommend against this; use Int32.TryParse.
You can leverage implicit and explicit operators to do what you want, yes. You can also use int.TryParse to avoid using exceptions for control flow.
public struct SafeInt
{
public int Value { get; private set; }
public static implicit operator int(SafeInt safeInt)
{
return safeInt.Value;
}
public static explicit operator SafeInt(string obj)
{
return new SafeInt() { Value = SafeParse(obj) };
}
public static int SafeParse(object value)
{
int output;
int.TryParse((value ?? "0").ToString(), out output);
return output;
}
}
I mean, you should use int.TryParse, but if you're dead-set on the cast syntax:
public class SafeInt
{
private int _value;
private SafeInt() {}
public static explicit operator SafeInt(string str)
{
int x;
int.TryParse(str, out x);
SafeInt si = new SafeInt();
si._value = x;
return si;
}
public static implicit operator int(SafeInt x)
{
return x._value;
}
public override string ToString()
{
return _value.ToString();
}
}
You can then use it like this:
int x = (SafeInt)"234234";
First, let me just go on record saying that you may not want to do this.
Silently ignoring problems like this can cause other types of problems, such as a customer asking "Why is this total over here always wrong?".
Having said that, let's see how you can do what you want before I give you a better option:
void Main()
{
int a = (SafeInt)"123";
a.Dump();
int b = (SafeInt)"xyz";
b.Dump();
}
public struct SafeInt
{
private readonly int _Value;
public SafeInt(int value)
{
_Value = value;
}
public SafeInt(int? value)
{
_Value = value ?? 0;
}
public int Value
{
get
{
return _Value;
}
}
public static implicit operator int(SafeInt s)
{
return s.Value;
}
public static implicit operator SafeInt(string s)
{
try
{
return new SafeInt(Convert.ToInt32(s));
}
catch (FormatException)
{
return new SafeInt();
}
}
}
This will print out:
123
0
Now, my advice is to stay away from this. Instead, use this:
void Main()
{
TryParse("123").Dump();
TryParse("xyz").Dump();
}
public static int TryParse(string s, int errorValue = 0)
{
int result;
if (int.TryParse(s, out result))
return result;
return errorValue;
}
Note that if you always want 0 as the value to return upon an error, there's even a much simpler way built into the system, this:
int value;
int.TryParse("123", out value);
Here we disregard the Boolean result from TryParse, because if TryParse fails, it'll set the parameter to 0.
I'd recommend that you do not do this. I find explicit and implicit conversions to be hard to discover, read, and use, compared to simpler static methods and/or constructors. Also, are you aware of the int.TryParse method? That might be a better solution for you:
public static int SafeInt(object value)
{
int i;
int.TryParse(value.ToString(), out i);
return i;
}
Or, more directly to answer your question, you can use explicit and implicit conversions on a SafeInt class to do this:
public class SafeInt
{
public int Value { get; set; }
public static implicit operator int(SafeInt si)
{
return si.Value;
}
public static explicit operator SafeInt(String str)
{
return new SafeInt { Value = Libs.str.safeInt(str) };
}
}
Use like:
int i = (SafeInt)"123";

more elegant design about enum

I'm on learning for C#.
I heared C# is one of the most constructible language. so would you guys make my code more elegant and efficient?
public class ISO639
{
public enum ISO639Code
{
Afrikaans, //af
Albanian, //sq
Amharic, //am
...
Yiddish, //yi
Unknown
}
public static string GetISO639CodeString(ISO639.ISO639Code l)
{
switch (l)
{
case ISO639Code.English: return "en";
case ISO639Code.Japanese: return "ja";
...
case ISO639Code.Hebrew: return "he";
default: return "";
}
public static ISO639.ISO639Code GetISO39CodeValue(string s)
{
switch (s)
{
case "ko" : return ISO639Code.Korean;
case "en" : return ISO639Code.English;
...
case "hu" : return ISO639Code.Hungarian;
default: return ISO639Code.Unknown;
}
}
}
Here is a my class ISO639. This class provides enum for ISO639 code, but I need a type conversion on from ISO639 enum to plain string. (ex. ISO639.ISO639Code.Italian => "it"). I also need a type conversion from plain string to ISO639 enum. (ex. "it" => ISO639.ISO639Code.Italian).
Is there a more efficient coding style for that?
You can add standard System.ComponentModel.Description attribute to each enum entry and then read it.
public enum ISO639Code
{
[Description("af")]
Afrikaans
}
public static class EnumExtensions
{
// Extension method to read Description value
public static string GetDescription(this Enum currentEnum)
{
var fi = currentEnum.GetType().GetField(currentEnum.ToString());
var da = (DescriptionAttribute)Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
return da != null ? da.Description : currentEnum.ToString();
}
}
// **How-to read it**
ISO639Code isoCode = ISO639Code.Afrikaans;
// this will returns "af"
string isoDescription = isoCode.GetDescription();
EDIT:
string searchFor = "af";
ISO639Code foundEntry;
// Loop through all entries descriptions
var allEntries = Enum.GetValues(typeof(ISO639Code));
foreach (var entry in allEntries)
{
// If you will extract this as separate method and use it for search not only loop
// through the all entries - you can put here is yield return description
var currentEntry = ((ISO639Code)entry);
string description = currentEntry.GetDescription();
if (description == searchFor)
{
foundEntry = currentEntry;
break;
}
}
Sure. You can use attributes:
public enum ISO639Code
{
[CodeString("af")] Afrikaans,
[CodeString("sq")] Albanian,
}
Use dictionary, for example: new Dictionary<ISO639Code, string>.
I suggest you to use C# extension methods to enums, they allow you to add whatever logic you want.
For example, see http://pietschsoft.com/post/2008/07/c-enhance-enums-using-extension-methods.aspx
I'd simply store the information in a dictionary-like object. This way you can reference the name by key and get the value directly.
You have an enum:
public enum ISO639Code
{
Afrikaans = 1,
Albanian = 2,
Amharic = 3,
etc.
Create a database table:
ISO639Id int PK,
ISO639Code char(2)
Where the ISO639Id maps to the value of the enum.
In code you'd want a ISO630 Class containing Id and Code values read from the database.
(You can load this once and then cache it in memory.)
The beauty of this approach, is it can be easily extended so that if in future you wanted to store more pieces of information for each ISO639 code, you could simply add another field.
Look at System.Globailzation namespace. The functionality you require looks to be already implemented there. At worst you can see the architecture and technique applied in the .Net framework to solve a very similar problem.
Enumerations are really good to work in code, as they are really strongly typed and make refactoring easier.
Follow these steps:
Use attributes for whatever extra information you want to attach to an enum. Usually this is a simple Description attribute. Something like:
public enum IsoCodes
{
[Description("af")]
Africans = 0,
[Description("am")]
Americans = 1
}
Then write some extension methods to convert strings and integers to and from this enum:
public static string GetDescription(this Enum value)
{
var entries = value.ToString().Split(FlagEnumSeparatorCharacter);
var description = new string[entries.Length];
for (var i = 0; i < entries.Length; i++)
{
var fieldInfo = value.GetType().GetField(entries[i].Trim());
var attributes = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];
description[i] = (attributes.Length > 0) ? attributes[0].Description : entries[i].Trim();
}
return String.Join(", ", description);
}
public static int GetValue(this Enum value)
{
return (int)value.GetType().GetField(value.ToString()).GetRawConstantValue();
}
public static T ToEnum<T>(this string value)
{
if (typeof(T).BaseType.Name != typeof(Enum).Name)
{
throw new Exception("Not an enum");
}
return (T)Enum.Parse(typeof(T), value, true);
}
public static T ToEnum<T>(this int value)
{
if (typeof(T).BaseType.Name != typeof(Enum).Name)
{
throw new Exception("Not an enum");
}
return (T)Enum.ToObject(typeof(T), value);
}
Now use your enums as you like.
I would go with having ISO639Code as class instead of enum:
public class ISO639Code
{
public string Value { get; set ; }
public string Code { get; set; }
public ISO639Code()
{
this.Value = "";
this.Code = "";
}
public ISO639Code(string value, string code)
: this()
{
this.Value = value;
this.Code = code;
}
public override bool Equals(object obj)
{
if (obj != null)
{
if (obj is string)
return obj.ToString().Equals(this.Value, StringComparison.CurrentCultureIgnoreCase);
if (obj is ISO639Code)
return ((ISO639Code)obj).Value.Equals(this.Value, StringComparison.CurrentCultureIgnoreCase);
}
return false;
}
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
public override string ToString()
{
return this.Value;
}
}
Then have global List<ISO639Code> with all possible codes, and to find specific code based on code name or value, just search for this in the List.
Personally, I prefer this over tweaking the enum.

SubSonic SimpleRepository storing member class

I'm new to C# and Subsonic. I'm trying to solve the following case:
public class UnknownInt {
public int val;
public bool known;
}
public class Record {
public int ID;
public UnknownInt data;
}
I'm using SimpleRepository.
Is there a way I can get UnknownInt serialized before storing it in the SQL database (perhaps as XML text field?)
I'm trying to build a questionnaire system in which a user can provide an 'integer' answer, an 'Unknown' answer, as well as a Null answer (question not answered yet)
In other words - what interfaces does my UnknownInt class need to implement in order to be eligible and convertible into SubSonic 3.0 Simple Repository?
Cheers!
I would do this:
public class Record
{
public int ID {get;set;}
[EditorBrowsable(EditorBrowsableState.Never)]
public int UnknownIntValue {get;set;}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool UnknownIntKnown {get;set;}
[SubSonicIgnore]
public UnknownInt UnknownInt
{
get
{
return new UnknownInt()
{
val = UnknownIntValue,
known = this.UnknownIntKnown
};
}
set
{
this.UnknownIntValue = value.val;
this.UnknownIntKnown = value.known;
}
}
}
public struct UnknownInt
{
public readonly int Val;
public readonly bool Known;
public UnknownInt(int val, bool known)
{
this.Val = val;
this.Known = known;
}
public override string ToString()
{
return String.Format("{0} ({1})",
Val, Known == true ? "known" : "unknown");
}
public override bool Equals(Object obj)
{
return obj is UnknownInt && this == (UnknownInt)obj;
}
public static bool operator ==(UnknownInt x, UnknownInt y)
{
return x.Val == y.Val && x.Known == y.Known;
}
public static bool operator !=(UnknownInt x, UnknownInt y)
{
return !(x == y);
}
}
The basic idea is to have to columns that store your userdefined type but are hidden from intellisense (System.ComponentModel.EditorBrowsable attribute).
Than you have a complex type (I prefer a struct rather than a class in this case) that is hidden from SubSonic's simple repository. The overrides and operator overloads are optional but make working with this type easier.
Example usage:
// 1. Step Create item1
var item1 = new Record();
item1.ID = 1;
item1.UnknownInt = new UnknownInt(1, true);
// 2. Setp Create item2
var item2 = new Record();
item2.ID = 2;
item2.UnknownImt = new UnknownInt(1, false);
if (item1.UnknownInt == item2.UnknownInt)
Console.WriteLine("???");
else
Console.WriteLine("Profit!!!");
Try using a nullable int (int?) instead of you UnknownInt class - you can store it via subsonic. No XML conversion needed!

Looking for a syntactic shortcut for accessing dictionaries

I have an abstract base class that holds a Dictionary. I'd like inherited classes to be able to access the dictionary fields using a convenient syntax. Currently I have lots of code like this:
string temp;
int val;
if (this.Fields.TryGetValue("Key", out temp)) {
if (int.TryParse(temp, out val)) {
// do something with val...
}
}
Obviously I can wrap this in utility functions but I'd like to have a cool, convenient syntax for accessing the dictionary fields where I can simply say something like:
int result = #Key;
Is there any way to do something like this in C# (3.5)?
You could add an indexer to your class and pass the indexer's parameter through to the dictionary.
class Foo
{
// Initialized elsewhere
Dictionary<String,String> Fields;
public Int32 this[String key]
{
String temp = null;
Int32 val = 0;
if (this.Fields.TryGetValue(key, out temp)) {
Int32.TryParse(temp, out val);
}
return val;
}
}
Then given an instance of Foo called foo you could do this:
Int32 value = foo["Key"];
How about an extension method?
public static int TryGetInt(this IDictionary dict, string key)
{
int val;
if (dict.Contains(key))
{
if (int.TryParse((string)dict[key], out val))
return val;
else
throw new Exception("Value is not a valid integer.");
}
throw new Exception("Key not found.");
}
The closer you can get to a nice syntax is using extension methods:
public static class MyDictExtensionMethods
{
public static T Get<T>(this Dictionary<string, object> dict, string key)
where T: IConvertible
{
object tmp;
if (!dict.TryGetValue(key, out tmp))
return default(T);
try {
return (T) Convert.ChangeType(tmp, typeof(T));
} catch (Exception) {
return default(T);
}
}
}
Usage:
int val = this.Fields.Get<int>("Key");
You can then create additional overloads for specific types (i.e.: types that does not implement IConvertible and need specific conversion).
Assuming that it's not always an int you want (if it is, then why isn't it a Dictionary<string, int>?) - I think something like this works and gets pretty close:
int i = #int["Key"];
string s = #string["Key"];
object o = #object["Key"];
This combines the fact that identifiers can be prefixed with # (it's usually optional, but it's required if your identifier is a reserved keyword, like int or string) with the default indexed parameter from Andrew Hare's answer.
It does require another class to be used to get the indexing - though if you wanted to use parens instead of square brackets for the key name, you could use methods instead:
int i = #value<int>("Key");
Implementation would be something like:
class DerivedClass : BaseClass {
void Main() {
int i = #int["Key"];
}
}
abstract class BaseClass {
private Dictionary<string, string> D { get; set; }
protected Indexer<int> #int = new Indexer<int>(s => int.Parse(s), this);
protected Indexer<string> #string = new Indexer<string>(s => s, this);
protected Indexer<object> #object = new Indexer<object>(s => (object)s, this);
protected class Indexer<T> {
public T this[string key] {
get { return this.Convert(this.BaseClass.D[key]); }
}
private T Convert(string value) { get; set; }
private BaseClass { get; set; }
public Indexer(Func<T, string> c, BaseClass b) {
this.Convert = c;
this.BaseClass = b;
}
}
}
Or, the method route:
class DerivedClass : BaseClass {
void Main() {
int i = #value<int>("key");
}
}
abstract class BaseClass {
private Dictionary<string, string> D { get; set; }
protected T #value<T>(string key) {
string s = this.D[s];
return Convert.ChangeType(s, typeof(T));
}
}
After reading through the language spec - if you're not tied to #, _ is a legal identifier. Combine that with indexers and you get:
int i = _["key"];

Categories

Resources