Linq表达式如何确定平等?

我正在考虑使用Linq Expression作为字典中的键。 但是,我担心我会得到奇怪的结果,因为我不知道Linq表达式如何确定Equality。

派生自Expression的类是否比较值相等或引用相等? 或者换句话说,

Expression<Func> first = () => new object(); Expression<Func> second = ()=>new object(); bool AreTheyEqual = first == second; 

您的测试比较表达式 。 表达本身只提供参考平等; 你的测试可能会显示“假”。 为了获得语义上的平等,你需要做很多工作,例如:

 x => 123 

 y => 123 

当量? 作为原始测试,您可以比较ToString(),但这将非常脆弱。

比较任何非值类型的对象(包括表达式)与==比较对象引用,因此它们将不相等。 然而,正如一位评论者指出的那样,字典将使用EqualsGetHashCode来确定相等性,这仍然会默认最终确定它们不相等。

您可以创建一个inheritanceSystem.Linq.Expression的类,并覆盖GetHashCodeEquals以某种方式使用结果,并将其用作字典的键。

正如其他人所指出的,Expression的==运算符使用默认的“引用相等”检查 – “它们是否都是对堆中相同位置的引用?”。 这意味着像您的示例之类的代码可能会返回false,因为您的表达式文本将被实例化为不同的Expression实例,而不管语义是否相等。 使用lambdas作为事件处理程序有类似的挫败感:

 MyEvent += (s, a) => DoSomething(); ... MyEvent -= (s, a) => DoSomething(); //<-- will NOT remove the added handler 

检查语义相等是很棘手的。 在这种特殊情况下,您可以访问表达式树的所有节点,并比较所有字符串,值类型和方法引用,以确定它们执行相同的操作。 但是,通过检查,以下示例中的两个lambdas在语义上是等效的,但是您很难编写一个方法来certificate它:

  public void MyMethod() {...} public void AnotherMethod { MyMethod(); }; ... Action one = () => MyMethod(); Action two = () => AnotherMethod(); var equal = one == two; // false