如何检查两个Expression <func <t,bool =“”>&gt;是相同的</func <t,>

时间:2009-03-23 12:31:25

标签: c# expression equality

是否有可能找出两个表达式是否相同?

给出以下四个表达式:

        Expression<Func<int, bool>> a = x => false;
        Expression<Func<int, bool>> b = x => false;
        Expression<Func<int, bool>> c = x => true;
        Expression<Func<int, bool>> d = x => x == 5;

然后,至少我们可以看到:

  • a == b
  • a != c
  • a != d

但我可以在我的代码中做任何事情来解决这个问题吗?

在msdn库中查看一下

  

Equals:确定指定的Object是否等于当前Object。 (继承自Object。)

我猜这意味着至少Expression类没有覆盖equals方法成为Equatable?那你怎么做?或者我在这里要求太多了? :P

3 个答案:

答案 0 :(得分:34)

您可以查看ExpressionEqualityComparer中使用的Linq to db4o类型。它实现了接口IEqualityComparer&lt; T&gt;,因此它可用于通用集合,也可用于独立使用。

它使用类型ExpressionComparison来比较两个表达式的相等性,并使用HashCodeCalculation来计算表达式中的哈希码。

这一切都涉及访问表达式树,所以如果你反复这样做可能会非常昂贵,但它也可以非常方便。

该代码在GPL或dOCL

下提供

例如,这是你的测试:

using System;
using System.Linq.Expressions;

using Db4objects.Db4o.Linq.Expressions;

class Test {

    static void Main ()
    {
        Expression<Func<int, bool>> a = x => false;
        Expression<Func<int, bool>> b = x => false;
        Expression<Func<int, bool>> c = x => true;
        Expression<Func<int, bool>> d = x => x == 5;

        Func<Expression, Expression, bool> eq =
            ExpressionEqualityComparer.Instance.Equals;

        Console.WriteLine (eq (a, b));
        Console.WriteLine (eq (a, c));
        Console.WriteLine (eq (a, d));
    }
}

它确实打印出真,假,假。

答案 1 :(得分:17)

作为一个懒惰的答案,你可以检查ToString() - 它至少应该指明它们明显不同的地方(虽然它会包含var-name,所以必须是相同的)。< / p>

准确地检查等价...更难 - 在很多不同的节点类型上做了很多工作。

答案 2 :(得分:4)

令我感到震惊的是,除了最简单的情况外,这可能很难做到。

例如:

var numbers1 = Enumerable.Range(1, 20);
Expression<Func<int, IEnumerable<int>>> a = x => numbers1;
var numbers2 = Enumerable.Range(1, 20);
Expression<Func<int, IEnumerable<int>>> b = x => numbers2;

从技术上讲,这些是相同的,但如何在不评估每个表达式中返回的IEnuemrable的情况下确定它?

相关问题