11

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

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

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

3 回答 3

11

您的测试比较表达式。表达式本身只提供引用相等;您的测试可能会显示“假”。为了实现语义平等,您需要做很多工作,例如 - 是:

x => 123

y => 123

相等的?作为一个粗略的测试,您可以比较 ToString(),但这会非常脆弱。

于 2011-02-17T18:22:37.770 回答
0

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

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

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

   public void MyMethod() {...}
   public void AnotherMethod { MyMethod(); };

   ...

   Action one = () => MyMethod();
   Action two = () => AnotherMethod();

   var equal = one == two; // false
于 2011-02-17T18:39:03.280 回答
0

用 == 比较任何两个不是值类型(包括表达式)的对象会比较对象引用,因此它们不会相等。但是,正如评论者指出的那样,字典将使用EqualsandGetHashCode来确定相等性,默认情况下仍会最终确定它们不相等。

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

于 2011-02-17T18:25:23.107 回答