Linq 表达式如何确定相等性?

发布于 2024-10-17 15:57:51 字数 338 浏览 3 评论 0原文

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

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

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

I am considering using a Linq Expression as a key in a dictionary. However, I am concerned that I will get strange results, because I don't know how Equality is determined by Linq expressions.

Does a class derived from Expression compare value equality or reference equality? Or in other words,

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

走走停停 2024-10-24 15:57:51

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

x => 123

y => 123

等价?作为粗略测试,您可以比较 ToString(),但这将非常脆弱。

Your test compares expressions. Expressions themselves offer only reference equality; your test will probably show "false". To cheek for semantic equality you would need to do a lot of work, for example - are:

x => 123

And

y => 123

Equivalent? As a crude test you can compare ToString(), but this will be exceptionally brittle.

泡沫很甜 2024-10-24 15:57:51

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

您可能可以创建一个继承 System.Linq.Expression 并重写 GetHashCode 和 Equals 的类以某种方式使用结果,然后使用它作为你字典的键。

Comparing any two objects that aren't value types (including an Expression) with == compares object references, so they won't be equal. As a commenter noted, though, a dictionary would be using Equals and GetHashCode to determine equality, which would still by default end up determining that they were not equal.

You could probably create a class that inherits System.Linq.Expression and override GetHashCode and Equals to use the result somehow, though, and use that as the key for your dictionary.

岁月苍老的讽刺 2024-10-24 15:57:51

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

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

As others have noted, Expression's == operator uses the default "reference equality" check - "Are they both a reference to the same place in the heap?". This means that code like your example will likely return false, since your expression literals will be instantiated as different Expression instances regardless of any semantic equality. There are similar frustrations with using lambdas as event handlers:

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

Checking for semantic equality is tricky. In this particular case, you might be able to visit all the nodes of the expression tree and compare all strings, value types and method references to determine that they do the same thing. However, by inspection, the two lambdas in the following example are semantically equivalent, but you'd have a hard time writing a method to prove it:

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

   ...

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

   var equal = one == two; // false
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文