I just can't find any proper piece of code to do what i need.
Im using Dict.ContainsKey but due to the fact im always creating the Key i need to look for, i always get false for the ContainsKey (because hashKey is different and im creating the key i want to check all the time).
can someone please advise how to override Contains key or how to handle keys comparing in this situation ?
My dictionary Looks like
Dictionary<someObj, int>
public class someObj
{
public int someobjParam {get;set;}
public int someobjParamTwo {get;set;}
}
You don't need to override ContainsKey - you need to either override Equals and GetHashCode in someObj (which should be renamed to conform to .NET naming conventions, btw) or you need to pass an IEqualityComparer<someObj> to the Dictionary<,> constructor. Either way, that code is used to compare keys (and obtain hash codes from them).
Basically you need to make Equals determine equality, and make GetHashCode return the same code for equal objects and ideally different codes for different objects - see Eric Lippert's article on GetHashCode for more details.
Also, you should consider making someObj immutable: mutable dictionary keys are generally a bad idea, as if you modify the key in a hashcode-sensitive way after using it as a key within the dictionary, you won't be able to find it again. If the point of your custom type really is to be a key, then just make it immutable.
For simplicity, you should also consider making someObj implement IEquatable<someObj>, and also think about whether it would be appropriate to be a struct instead of a class. If you implement IEquatable<someObj> you should also override object.Equals in a consistent way. Usually the object.Equals implementation will just call the most strongly-typed IEquatable<T>.Equals implementation.
You don't need to override ContainsKey, but rather instruct the dictionary when it should consider that two keys are equal.
One way to do that is by implementing IEquatable<someObj> in your key class. Do this if the concept of equality is global across your app:
public class someObj : IEquatable<someObj>
{
public int someobjParam {get;set;}
public int someobjParamTwo {get;set;}
// override GetHashCode() and Equals(); for an example
// see http://msdn.microsoft.com/en-us/library/ms131190%28v=vs.110%29.aspx
}
Another one is by implementing an IEqualityComparer<someObj> and passing it to the dictionary's constructor.
Related
I'm need to hash against a member variable instead of the class, so I don't check if the reference is in the dictionary. Without overriding the defaults, it won't find an identical Value, but only return if it finds the same exact instance of HashedType, such that this code fails.
Dictionary.Add(new HashedType(4));
Dictionary.Contains(new HashedType(4)); // fails to find 4
Definition of HashedType:
HashedType
{
public HashedType(Int32 value) { Value = value); }
public HashedType(String value) { Value = value); }
public object Value;
public void Serialize(Serializer s)
{
if (Value.GetType() == typeof(Int32))
{
s.Set<Int32>(0);
s.Set<Int32>(Value);
}
else
{
s.Set<Int32>(1);
s.Set<String>(Value);
}
}
}
It looks like I can override GetHashCode() and Equals() to do this for me.
However, MSDN recommends I create a separate class that I derive from IEqualityComparer and instantiate my dictionaries used HashedType with the HashedTypeComparer : IEqualityComparer.
To help make this easier, I've derived from Dictionary and created
HashedTypeDictionary<U> : Dictionary<T,U>
{
public HashedTypeDictionary() : base(new HashedTypeComparer()) { }
public bool Equals(HashedType a, HashedType b) { return a.Value == b.Value; }
publci int GetHashCode(HashedType a) { return a.Value.GetHashCode(); }
}
This all seems contrived.
Is the only advantage I get is not changing the Equals()?
I mean, really speaking, I would want Equals to compare against that single member anyway.
The idea is that object.Equals is the natural equality for that type (and GetHashCode should match that idea of equality). IEqualityComparer is used when you want a different equality on a case-by-case basis.
Consider for example, a string. The overridden Equals & GetHashCode methods do case-sensitive comparisons. But what if you want a dictionary where the keys are not case-sensitive? You write an IEqualityComparer that is not case-sensitive and pass it in the constructor of the dictionary.
Your examples sounds like any two instances of HashedType are to be normally treated as equal if their members are equal. In that case I'd recommend overriding the object.Equals and object.GetHashCode methods and not writing a IEqualityComparer.
The reason you would choose one over the other is whether you always want instances of a given type to be compared using a certain logic, or only in this one situation.
Equals and GetHashCode provide the "true" implementation of whether two objects are logically equal. IEqualityComparer allows you to override that in a case-by-case basis, and to separate ownership (it might be different parties who control the entities versus the code using them).
Imagine, for a moment, that you don't own the underlying class (i.e. it's produced by another team, or only given to you as a binary). You always can create the IEqualityComparer. You might not have the option of changing Equals and GetHashCode...
If the majority of the time you want the Dictionary behavior to work by default override GetHashCode and Equals. Bear in mind for this to work they must never change during the lifecycle of the object - so if they are running off Value then Value should be set in the constructor and a read-only property.
IEqualityComparer is really used for when you want to compare things differently in one section of your program.
I am trying to do something along the lines of the following:
class Test
{
public string Name { get; set;}
public string Location { get; set;}
public Test(string name, string location)
{
Name = name;
Location = location;
}
}
Now, in a method in another class, I am trying to add these Test classes into a Dictionary with a KeyValuePair of
Dictionary<Test,int> resources = new Dictionary<Test,int>();
resources.Add(new Test("First Resource", "Home"), 1);
Now, what I am trying to do, and need to be able to do is:
bool contains = resources.ContainsKey(new Test("First Resource", "Home"));
resources[new Test("First Resource", "Home")] = 2;
As of now, this returns false. How can I get this to return true?
I have tried overriding the Equals function of my Test class and even implementing IComparible and doing custom comparisons.
You need to override GetHashCode in your Test class, add the following to your class:
public override int GetHashCode()
{
return (Name+Location).GetHashCode();
}
This will ensure that any two Test instances have the same hash only if the concatenation of Name and Location are the same. You could use other strategies for this, however, this is the simplest form.
You need to implement GetHashCode and Equals in the key class or provide an IEqualityComparer<Test> implementation in the constructor of the dictionary.
In the case of the comparer, you would define proper GetHashCode and Equals methods inside the comparer for Test, with the benefit that these implementations are not universal for all Test objects, but can be used at will when necessary (such as for use in dictionaries, hashsets, various Linq queries, etc.) By decoupling the equality and hashcode functions from the class, you are then free to use different implementations of the comparer as the need arises.
(For a good set of guidelines on GetHashCode, please visit this blog.)
Dictionary uses GetHashCode of the key to determine in which data bucket to store an object, and then Equals to make sure that the objects are actually equal. In other words, for this to work, you will need to implement GetHashCode() and Equals for your type.
It is considered good practice to make objects used for keys in a dictionary immutable. If the object changes, its hashcode changes, and you might not be able to find it in the dictionary.
I have a program that have to manage objects with a composite key.
this key, to be simple is a couple of strings.
I have the following code :
public struct MyKey
{
public string Part1 { get; set;} // always set
public string Part2 { get; set;} // can be null
public MyKey(string part1, string part2) : this()
{
this.Part1 = part1;
this.Part2 = part2;
}
}
this is ok for storing my values.
Now I want to be able to :
use the equals operator (part1 and part2 are equals)
use the key in a Dictionnary, especially for using Contains method
I've guessing a number of things (override equals operator, overriding GetHashCode and Equals methods, implementing IComparable, etc.), but I'm not sure what are the necessary steps to reach my goals and what will cause an overhead.
thx in advance
Use .NET 4.0 Tuple, it has a correct Equals() and GetHashCode() based on the component values. I've used Tuple before or if they are string keys you can always concat with a separator, but if you truly want to keep that class as your key you do want a proper Equals() and GetHashCode(), so in that case have YourType implement IEqualityComparer<YourType>.
p.s. Here's a good example of overriding the GetHashCode() if you want to do that manually instead of a Tuple...
What is the best algorithm for an overridden System.Object.GetHashCode?
You need to override Equals and GetHashCode in order to use your object as a key in a dictionary. This answer provides an excellent explanation.
First of all, I would stay away from struct because of boxing and various coding pitfalls it can fall us into.
I would override both GetHashCode and Equals. GetHashCode since it is used in dictionaries and Equals since it is used by various ORMs and can be handy in implementing business logic.
I am refactoring a C# library that uses a Dictionary<int, SomeInterface> all over the system.
I need to change the key type from int to string, and use a Dictionary<string, SomeInterface> instead, and I am making dozens of changes.
How to do it better, how to define a type in one place and uses it everywhere, so that if I need to change it later, I can change it in one place?
I already added a GetKey() method to my interface.
Edit: the library is used in other DLLs, and I want to limit possible changes to only one library. This is an agile shop, so we need to be ready for changes.
If swapping the type of key is important to you, consider a custom class wrapping the underlying key.
e.g, public class Key { public Key(object adaptee) { ... } }
Remember to implement Equals() and GetHashCode() and just delegate to the underlying object.
I'm not sure if this helps your particular scenario, but in general, Resharper is a fantastic tool to help assist with these types of changes.
Create you own keyType that is:
a struct
contains a int field
has converter to/from int (marked as obsolete)
has GetHashCode() and Equal() methods that call the methods on the field
Start to use the keyType
Use the obsolete complier warning to guid you
Once all the Dictionarys are using the new keyType and you are getting no more obslete warning, then convert the type of the field inside of keyType
I have quite a few dictionaries where the key is a composite of several different values (mostly strings and integers). Do I implement these keys as classes (and override GetHashCode(), Equals() etc) or do I use struct instead?
ReSharper makes it easy to do the overriding, but the code looks horrible. Are there any performance implications of using a struct instead?
If your only problem is defining equality for the use in a Dictionary<TKey,TValue> then another path you may choose is implementing an IEqualityComparer<T>. This can be manually passed to the dictionary constructor and take care of equality comparisons for the TKey value without modification to the key type.
If you have the more general problem of defining equality for your composite values then I would focus on making the composite value natively support equality. Yes, defining the full set of methods necessary for equality is a pain but it's mostly boiler plate code. Getting it right is more important than whether or not the boiler plate code looks messy.
I would actually say that for any struct one should always manually code an override of Equals() and GetHashCode() along with implementing IEquatable<T>, if it's at all likely that it could be used by someone as a key, so I certainly wouldn't use it just to avoid doing so.
As well as requiring boxing, the default implementation is rather slow as it uses reflection to examine the fields. There are also a bug in at least some framework versions (the implementation quite wisely optimises as a binary compare when doing so will give the correct results, but unfortunately mis-judges when this is the case, and hence two structs containing equivalent decimal fields may be considered unequal).
When a quick composite is needed that doesn't really have any meaning to the system besides being a composite key, I'd recommend using Tuple. Tuple.Create() makes it easy to compose them, and the overrides for Equals() and GetHashCode() are pretty reasonable.
In some cases it can also be suitable to use anonymous classes as keys (only within the context of a given method of course), and here the overrides for Equals() and GetHashCode() are pretty reasonable too.
To create such a composite class, the recommended technique is to inherit from Tuple<int, string, ...>.
This way, you don't have to override GetHashCode and Equals yourself, the base class does it for you.
You can easily provide meaningful get accessors for each fields.
public class CompositeKey : Tuple<string, int>
{
public CompositeKey(string name, int age)
: base(name, age)
{
}
public string Name { get { return Item1; } }
public int Age { get { return Item2; } }
}
This also enforces immutability, which is appropriate for dictionary keys.
As for performance, the builtin Tuples are quite fast. I found custom structs can be faster, though if you really need every extra bit of performance, the best is to encode directly your key data into an int or long.