Dictionary of a class - c#

I have a dictionary
public static Dictionary<SymbolAndStrategy, int> allPositions
SymbolAndStrategy is a class containing 2 different class, Class Symbol and Class Strategy. But when I tried to use it like as this,
allPositions.Add(new SymbolAndStrategy(StrategyName.Apple, this.ProductKey), 0);
allPositions[new SymbolAndStrategy(StrategyName.Apple, this.ProductKey)]++;
the compiler will complain "key not found" even the 2 have the SymbolAndStrategy key.

The complain of the compailer is probabbly derives from the fact that you didn't override GetHashCode() and Equal() methods of your type in order to make equal 2 different instances by their content.
In short
new SymbolAndStrategy(StrategyName.Apple, this.ProductKey) create a new instance, a new allocation. In order to "explain" to the framework that those 2 instances are equal (the one present in the dictionary as a key, and another you use for a query) you need to override those 2 methods mentioned above accordingly inside SymbolAndStrategy type.
More on that Implementing the Equals Method

That's the expected behaviour because reference types are compared by reference. Even though your objects have the content they are not treated as equal because they have different references. If you don't want this you need to override Equals and GetHashCode method in your class.
Or you can implement an IEqualityComparer for your class and pass it to Dictionary constructor, so it will be used instead of the default comparison.

The issue is the fact that, by default, Dictionary<TKey, TValue> will use Object.Equals to test for key equality. If you didn't override Equals and GetHashCode in your class, then Object.Equals will use reference equality. Since you're creating two instances of your key (albeit with the same values), Object.Equals will return false.
There are two solutions.
Override Equals and GetHashCode in your class.
Use the Dictionary<TKey, TValue> constructor that takes an IEqualityComparer<TKey>. That will allow you to implement an equality check without having to modify the original class if you don't have the ability.

Related

C# override Dictionary ContainsKey

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.

C#: Using ContainsKey where the keys are objects

Ok so I need a bit of help. I have a generic dictionary "cashdata". The keys of this dictionary are objects (Query objects, a class I have defined). Query objects have "Terms" field, which is a list of strings, and an "Operator" field, which is an enum (Either "All" or "Any").
cashdata.ContainsKey(a_query_object);
And have it yield true or false depending on if a_query_object and an object in the dictionary are identical in terms of their Terms and Operator. What is the best way to do this? A HashCode possibly? I would appreciate an example, thanks in advance.
EDIT: cashdata Dictionary is defined as such
Dictionary<Query,List<string> > cashData = new Dictionary<Query,List<string>>();
Make your object implement IEquatable Interface along with overriding Object.Equals and GetHashCode as mentioned in the remarks section in MSDN
If you implement IEquatable, you should also override the base
class implementations of Object.Equals(Object) and GetHashCode so that
their behavior is consistent with that of the IEquatable.Equals
method. If you do override Object.Equals(Object), your overridden
implementation is also called in calls to the static
Equals(System.Object, System.Object) method on your class. In
addition, you should overload the op_Equality and op_Inequality
operators. This ensures that all tests for equality return consistent
results.

When to use a GUID for a class

I'm working on a simple application with a few classes. This all started when I wanted to use the Remove method on a List<Car>. This method requires that you override the Equals and the GetHashCode methods for the Car type. In this situation, I decided to implement an ID property on the Car class. That way, my Equals method simply checks for ID equality, and my GetHashCode method returns base.GetHashCode().
Is this a good approach, or is implementing a GUID for a small class too heavy-handed? There wouldn't be any need for it without the reasons I explained above. The only requirement for uniqueness for this Car type is that it be unique within the List<T> collection to which it belongs. But adding the GUID property seemed like the quickest way around the GetHashCode mess. BTW, there are no int properties on my Car type.
There wouldn't be any need for it without the reasons I explained above.
If your class doesn't logically have an ID, then it certainly seems odd to include it just for the sake of equality.
For example, if you have two instances which have equal properties for everything apart from ID, are they really non-equal? If they are, you should potentially just use the default implementation of Equals/GetHashCode which uses reference identity for equality. Where you would use two objects with the same ID, you just use two references to the same object instead.
It really all depends on the context, and you haven't given much of that - but adding an ID just for equality is a bit of a design smell.
Instead of implementing Equals and GetHashCode just use RemoveAll:
myList.RemoveAll(x => x.ID == myCar.ID);
This allows you to specify a predicate that indicates what items should be removed instead (it doesn't matter that you are only removing one item).
Implementing Equals and GetHashCode in the way you describe strikes me as extremely dodgey - if your Equals implementation returns true then your GetHashCode method needs to return the same value so that those two objects will be placed in the same bucket in a hashtable. Your implementation (as I understand it) doesn't match this criteria as the base GetHashCode implementation is almost certainly going to return different values for two Car instances, regardless of if they have the same ID or not.
Implementing Equals and GetHashCode isn't entirely trivial and is probably something I'd generally avoid doing if there are alternatives. If you really want to do this then take a look at these resoruces:
What is the best algorithm for an overridden System.Object.GetHashCode?
Default implementation for Object.GetHashCode().
implementing the Equals method
Also hash codes are not GUIDs

Advantage of deriving external class from IEqualityComparer<> over overriding GetHashCode and Equals

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.

should all c# classes implement Equals and GetHashCode?

should all c# classes override Equals and GetHashCode? For correctness
No, they already do.
Whether you have to override them, is up to how it will be used. In most cases, it is not needed.
All classes already inherit these methods from the base class, System.Object.
You can choose to override the methods in derived classes if you need to be able to compare two instances of an object beyond simple reference equality, otherwise it's not necessary.
Remember, however, that if you choose to override one of them, you also need to override the other in order to ensure that Hashtables and dictionary keys, among other things, work properly with you derived class. The GetHashCode method needs to reflect the same logic as the Equals method. See here for more explanations and examples:
http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx
and
http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx
All classes to inherit this from the System.Object.
If you need to provide a specific Equals or GetHashCode for a class then you should override the methods in your classes. Otherwise just leave them..
http://msdn.microsoft.com/en-us/library/system.object.gethashcode(v=VS.71).aspx
Maybe not all, but all classes that will be put into a some kind of bag (IList, ICollection, IDictionary, Hashset, etc.) and need some simple method to differentiate them (just think about Sort(), Contains(), BinarySearch(), etc.).
If you use a class that way you should definitely implement them correct.
When you override Equals, basically.
When you want to provide a different
idea of equality than simple reference
equality.
String is a good example of this - two
strings are equal (under a simple
Equals call) if they represent the
same sequence of characters. The hash
code reflects this, such that if two
strings are equal they will have the
same hash code. (The reverse isn't
necessarily true - two unequal strings
can have the same hash code, but it's
unlikely.)
(Strings are tricky in other ways,
mind you - there are lots of different
ideas of equality based on culture and
casing, but String.Equals just looks
at the UTF-16 code points which make
up the string, and compares them in
the simplest conceivable fashion.)
by Jon Skeet

Categories

Resources