patterncsharpMinor
Custom key class for .NET 3.5 framework
Viewed 0 times
customnetforclasskeyframework
Problem
I use .NET 3.5 framework, so no tuples. I have many use cases where I have to create a custom key for a dictionary. How can I make this better?
Especially this part:
The challenge is to have lambda defined only once, but have different key objects based on the POCO.
public class CompositeKey
{
public T Content { get; set; }
public Func[] Lambdas { get; set; }
public CompositeKey(T obj, params Func[] propLambdas)
{
Content = obj;
Lambdas = propLambdas;
}
public override int GetHashCode()
{
int hash = 0;
foreach (var l in Lambdas)
{
hash ^= l(Content).GetHashCode();
}
return hash;
}
public override bool Equals(object obj)
{
bool isEqual = true;
if (obj is T)
{
T o = (T)obj;
foreach (var l in Lambdas)
{
isEqual &= (l(Content) == l(o));
}
return isEqual;
}
return false;
}
}
public class TestCode
{
public void somemethod()
{
Dictionary, string> dict = new Dictionary, string>();
var t1 = new TestPOCO() { ID=1, Name="A" };
var t2 = new TestPOCO() { ID = 2, Name = "B" };
dict.Add(new CompositeKey(t1, x => x.ID, x => x.Name) , t1.Name);
dict.Add(new CompositeKey(t2, x => x.ID, x => x.Name), t2.Name);
}
}
public class TestPOCO
{
public int ID;
public string Name;
}Especially this part:
dict.Add(new CompositeKey(t1, x => x.ID, x => x.Name) , t1.Name);
dict.Add(new CompositeKey(t2, x => x.ID, x => x.Name), t2.Name);The challenge is to have lambda defined only once, but have different key objects based on the POCO.
Solution
-
Mutable keys are a very bad idea, try this:
-
-
You can create a dictionary passing in an
-
About your example:
ID reads like a property that uniquely identifies an entity and does not change.
If this is the case it is a nice candidate to use as a key. I'm guessing a bit here but I'm getting a feeling you really want:
Mutable keys are a very bad idea, try this:
public void Foo()
{
var mutable = new Mutable { Value = 1 };
var dictionary = new Dictionary { { mutable, "one" } };
mutable.Value = 2;
var explodesHere = dictionary[mutable];
}
public class Mutable
{
public int Value;
public override int GetHashCode()
{
return Value;
}
}-
GetHashCode must not change while the instance is used in a collection that relies on the value. There are two ways to solve this:- Calculate the hash from values that cannot change. Prefer this wherever possible.
- Make sure that the values affecting the hash are not changed while the instance is used in a collection. This is a pit of failure.
-
You can create a dictionary passing in an
IEqualityComparer-
About your example:
ID reads like a property that uniquely identifies an entity and does not change.
If this is the case it is a nice candidate to use as a key. I'm guessing a bit here but I'm getting a feeling you really want:
var idNameMap = new Dictionary();
idNameMap.Add(t1.ID, t1.Name);Code Snippets
public void Foo()
{
var mutable = new Mutable { Value = 1 };
var dictionary = new Dictionary<Mutable, string> { { mutable, "one" } };
mutable.Value = 2;
var explodesHere = dictionary[mutable];
}
public class Mutable
{
public int Value;
public override int GetHashCode()
{
return Value;
}
}var idNameMap = new Dictionary<int, string>();
idNameMap.Add(t1.ID, t1.Name);Context
StackExchange Code Review Q#122514, answer score: 3
Revisions (0)
No revisions yet.