patterncsharpMinor
Generic wrapper for equality and hash implementation
Viewed 0 times
genericequalityhashwrapperforandimplementation
Problem
I was writing an answer in another thread and came across this challenge. I'm trying to have a generic class so that I can delegate the routine (and tiring)
Please note that I have no problem with performance as of now. But when writing a generic library for future use, I'm contemplating better designs. I'll include the bare minimum code required to drive the idea.
Approach 1
This is great considering it works for any number of properties. But performance sucks, boxing I believe is the culprit. Runs in around 260 ms for about 100000 calls to
Approach 2
Equals and GetHashCode implementation to it (which should handle all that). With the code things will be clearer.Please note that I have no problem with performance as of now. But when writing a generic library for future use, I'm contemplating better designs. I'll include the bare minimum code required to drive the idea.
Approach 1
public class Equater : IEqualityComparer
{
public IEnumerable> Keys { get; private set; }
public Equater(params Func[] keys)
{
Keys = keys;
}
public bool Equals(T x, T y)
{
----
}
public int GetHashCode(T obj)
{
.....
}
}
//an example usage
public class Dao : IEquatable
{
static Equater equater = new Equater(x => x.Id, x => x.Table);
public bool Equals(Dao other)
{
return equater.Equals(this, other);
}
public override int GetHashCode()
{
return equater.GetHashCode(this);
}
}This is great considering it works for any number of properties. But performance sucks, boxing I believe is the culprit. Runs in around 260 ms for about 100000 calls to
GetHashCode.Approach 2
public static class Equater
{
public static Func equals;
public static Func getHashCode;
public static void Set(Func key1Selector,
Func key2Selector)
{
equals = (x, y) =>
{
----
};
getHashCode = t => { .... };
}
//other overloads of Set with varying type arguments
}
//an example usage
public class Dao : IEquatable
{
static Dao()
{
Equater.Set(x => x.Id, x => x.Table);
}
public bool Equals(Dao other)
{
return Equater.equals(this, other);
}
public override int GetHashCode()
{
return Equater.getHashCode(this);
}
}Solution
You can reach maximum performance by generating specialized code at runtime using
That way you only have to execute one static field load and one delegate call per call to
Expression trees. Instead of injecting Funcs, inject Expression> s into your Equater class. Analyze what field they point to and build up the corresponding expressions for hashing and equality.That way you only have to execute one static field load and one delegate call per call to
Equals or GetHashCode.Context
StackExchange Code Review Q#25131, answer score: 3
Revisions (0)
No revisions yet.