给定lambda
表达式,我需要一种方法将已编译的委托存储在字典中,因此我不需要每次都编译它们。
我的第一次尝试是通过表达式转换为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; }
}
输出:
o => Convert(o).Prop
o => Convert(o).Prop
1
这种方法不起作用,因为Expression.ToString()
不够详细,无法提供相等性,而且它不可靠,因为一般不保证ToString
实现。
如何在不访问表达式节点的情况下正确实现Equals(Expression, Expression)
和GetHashCode(Expression)
?
如果表达式实例无法实现,是否可以使用其他语言构造,包装原始表达式,可用于获取所述表达式?
绝对要求,这使得这个问题与重复不同: 在与表达式的平均大小成比例的恒定摊销时间内工作,这是保持原始散列函数算法属性的要求。