51

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

就像给定以下四个表达式:

        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

4

3 回答 3

38

您可以查看在Linq to db4o中使用的ExpressionEqualityComparer类型。它实现了 IEqualityComparer<T> 接口,因此它可用于泛型集合,也可用于独立使用。

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

这一切都涉及访问表达式树,因此如果您重复执行它可能会非常昂贵,但它也可以非常方便。

该代码在 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));
    }
}

它确实打印了 True, False, False。

于 2009-03-23T12:44:49.117 回答
20

作为一个懒惰的答案,您可以检查ToString()- 它至少应该指出它们明显不同的地方(尽管它会在那里包含 var-name,所以它必须是相同的)。

为了准确地检查等价性......更加困难 - 大量工作,涉及许多不同的节点类型。

于 2009-03-23T12:50:19.663 回答
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,如何确定呢?

于 2009-03-23T12:38:05.357 回答