Linq表达式如何确定平等?

时间:2011-02-17 18:14:55

标签: c# linq lambda expression linq-expressions

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

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

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

3 个答案:

答案 0 :(得分:11)

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

x => 123

y => 123

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

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

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

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

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

   ...

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

   var equal = one == two; // false