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.
Related
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.
I need to write a second equality comparer for a business object. It is a specialized equality comparer which is only applicable in certain situations. I do not want to override the Equal() because our persistent layer uses that to compare objects internally for its own uses.
Let me give you an example of a class:
public class Product : BusinessObjectBase
{
string Name {get;set;}
string Desc {get;set;}
double Price {get;set;}
}
Since we mark the three properties as persistent data properties in our data access layer, the Equals() in the BusinessObjectBase compares those properties. Now, in a specific instance I would like to check if product A it equal to product B only be Name. I do not want to hardcode the actual property on the check because this property might change later.
While IComparer could be used here, but based on the description on MSDN, IComparer should be used not to equate items but to sort them, so that does not seem like a 100% correct answer.
I would like to use something .NET already has and not create another interface.
What is the best way to do this?
Thanks
You're looking for IEqualityComparer<T>.
I got reading this question here which led me to this article here.
I've got an abstract base class that allows me to constrain methods to accept only my classes that extend my abstract base class (basic polymorphism). My question is: Can I implement GetHashCode() in my abstract base class to provide a suitable override for any concrete implementation? (I.e. to avoid overriding GetHashCode() in each concrete class.)
I'm imagining a method in my abstract base class something like this:
public abstract class FooBase
{
private static readonly int prime_seed = 13;
private static readonly int prime_factor = 7;
public override int GetHashCode()
{
// Seed using the hashcode for this concrete class' Type so
// two classes with the same properties return different hashes.
int hash = prime_seed * this.GetType().GetHashCode();
// Get this concrete class' public properties.
var props = this.GetType().GetProperties(BindingFlags.Public);
foreach (var prop in props)
{
// Factor in each of this concrete class' public properties' hashcodes.
hash = (hash * prime_factor) + prop.GetHashCode();
}
return hash;
}
}
This seems to work in some basic equality unit tests but I feel like I've overlooked something. I still have to provide an override in each concrete class to avoid the compiler Warning about not overriding GetHashCode(), but at least this way I don't have to manually write an implementation for each one.
Does this perform better than:
public override int GetHashCode()
{
return 1;
}
A key to a Hash function is it must be fast to compute. With reflection, you might lose all the benefits you stand to gain from having a hash.
It would be worth it to benchmark.
Also, hash codes must be equal when Equals returns true, so will all subclasses use only public properties in their Equals method? If not, you might consider looping over all properties, not just public ones.
Edit to add:
Also, consider adding unchecked around your property loop to prevent an exception if the hash gets bigger than Int.MaxValue.
You missed a basic rule - GetHashCode() result must remain the same for the whole lifetime of the object. In your GetHashCode implementation, it isn't guaranteed (because the properties you are iterating can be mutable).
Using reflection is rather slow, but in some cases it is acceptable. The GetHashCode function is used when the instance of the class is a key in a hashtable or dictionary. In most cases you know when you need it. There are some tools, like Resharper (example) which can generate the GetHashCode and Equals functions for you instead of writing them manually.
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 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.