3

Given an lambda expression, I need a way to store a compiled delegate in a dictionary, so i don't need to compile them each time.

My first attempt was caching delegates by expression converted to string:

class ExpressionEqualityComparer : IEqualityComparer<Expression>
{
    public bool Equals(Expression a, Expression b)
    {
        return a.ToString().Equals(b.ToString());
    }
    public int GetHashCode(Expression e)
    {
        return e.ToString().GetHashCode();
    }
}
void Main()
{
    var e1 = (Expression<Func<object, string>>)(o => ((Model)o).Prop);

    Console.WriteLine(e1.ToString());

    d.Add(e1, e1.Compile());

    var e2 = (Expression<Func<object, string>>)(o => ((Model2)o).Prop);
    try
    {
        d.Add(e2, e2.Compile());
    }
    catch
    {
        // ArgumentException. An element with the same key already exists in the Dictionary< TKey, TValue >.
    }
    Console.WriteLine(e2.ToString());   
    Console.WriteLine(d.Count);
}
Dictionary<Expression, System.Func<object, string>> d = new Dictionary<Expression, System.Func<object, string>>(new ExpressionEqualityComparer());
class Model
{
    public string Prop { get; set; }
}
class Model2
{
    public string Prop { get; set; }
}

Output:

o => Convert(o).Prop
o => Convert(o).Prop
1

This approach does not work because Expression.ToString() is not detailed enough to provide equality, and it's not reliable since there is no guarantee about the ToString implementation in general.

How to implement Equals(Expression, Expression) and GetHashCode(Expression) correctly without visiting the expression nodes?

If it's not possible with expression instance, is it possible with some other language construct, wrapping the original expression, which can be used to obtain the said expression?

The absolute requirement, which makes this question different from duplicates: Working in constant amortized time proportional to average size of the expression, which is the requirement to keep original hash function algorithmic properties.

George Polevoy
  • 7,450
  • 3
  • 36
  • 61
  • 1
    http://stackoverflow.com/questions/283537/most-efficient-way-to-test-equality-of-lambda-expressions http://stackoverflow.com/questions/673205/how-to-check-if-two-expressionfunct-bool-are-the-same – Alex Krupka Oct 15 '15 at 13:14
  • The referenced duplicate provides detailed explanation for how to compare expressions for equality. This is easily extended to build a cache, by using the same technique to implement the hash code. If you have a _specific_ question not addressed by the other question, please provide [a good, _minimal_, _complete_ code example](https://stackoverflow.com/help/mcve) that reliably reproduces the problem, along with a precise, detailed explanation of what that code does and how that's different from what you want. – Peter Duniho Oct 15 '15 at 17:00

0 Answers0