Reputation: 9926
I want to create Dictionary that contain class XX that will be the key and class YY that will be the value.
The Dictionary is define as
Dictionary<XX, YY> myDictionary;
The XX class code
class XX
{
int t1;
char t2;
string Key()
{
return string.Format("{0}{1}", t1, t2);
}
}
I want somehow to define that the Dictionary key is actually XX but using the 'Key' of the class XX as the real key of the dictionary.
is it possible ?
Upvotes: 1
Views: 139
Reputation: 51330
You have to override two methods of XX
:
Equals
, which will tell the dictionary whether the two instances are equalGetHashCode
, which has to return the same number if two instances are equal. Note that it can return the same number if two instances aren't equal too, but you should make it as unique as possible.You can also implement IEquatable<XX>
on the XX
class, which will mkae it explicit that XX
can compare for equality.
class XX : IEquatable<XX>
{
int t1;
char t2;
public override bool Equals(object other)
{
return Equals(other as XX);
}
public bool Equals(XX other)
{
return other != null
&& t1 == other.t1
&& t2 == other.t2;
}
public override int GetHashCode()
{
return t1 ^ (397 * t2.GetHashCode());
}
}
Create a class which implements IEqualityComparer<XX>
and pass it to the dictionary's constructor. You will have to implement the same two methods, but the logic will be separated from XX
, and you will be able to create different dictionaries with different keying schemes.
class XXEqualityComparer : IEqualityComparer<XX>
{
public static readonly XXEqualityComparer Instance = new XXEqualityComparer();
private XXEqualityComparer()
{
}
public bool Equals(XX x, XX y)
{
if (ReferenceEquals(x, y))
return true;
if (x == null || y == null)
return false;
return x.t1 == y.t1
&& x.t2 == y.t2;
}
public int GetHashCode(XX obj)
{
return obj == null ? 0 : obj.t1 ^ (397 * obj.t2.GetHashCode());
}
}
Then:
var myDictionary = new Dictionary<XX, YY>(XXEqualityComparer.Instance);
Replace the dictionary with a KeyedCollection<XX, string>
. You will have to override the GetKeyForItem
method to provide a key for an item.
class XXKeyedCollection : KeyedCollection<XX, string>
{
protected override string GetKeyForItem(XX item)
{
return string.Format("{0}{1}", t1, t2);
}
}
Please note that in order to have a working dictionary key, the object must not change while it's used as a dictionary key. More precisely, any field/property that would influence the result of Equals
or GetHashCode
must not change.
Upvotes: 8
Reputation: 178
Dictionary class uses the GetHashCode() method on the key object to generate the key in the hash table. Just override it in XX class to return whatever you need, but be careful there (think what might happen if different XX instances with the same key are put in the dictionary).
Upvotes: 2