C# 如何检查两个表达式是否<;Func<;T、 布尔>&燃气轮机;都一样

C# 如何检查两个表达式是否<;Func<;T、 布尔>&燃气轮机;都一样,c#,expression,equality,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<

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

如以下四个表达式所示:

        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=x=>false;
表达式b=x=>false;
表达式c=x=>true;
表达式d=x=>x==5;
那么,至少我们可以看到:

  • a==b
  • a!=c
  • a!=d
但是我能做些什么在我的代码中找到这个吗

看了一眼msdn库,上面写着

等于
:确定指定的对象是否等于当前的
对象
。(继承自
对象


我想这意味着至少Expression类没有重写equals方法,使其成为Equalable?那么你会怎么做呢?还是我的要求太高了p

我觉得这可能很难做到,除非是在最简单的情况下

例如:

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;
var numbers1=可枚举范围(1,20);
表达式a=x=>numbers1;
var numbers2=可枚举范围(1,20);
表达式b=x=>numbers2;

从技术上讲,它们是相等的,但是如果不计算每个表达式中返回的IEnuemrable,如何确定它们呢?

您可以查看其中使用的类型。它实现了IEqualityComparer接口,因此它既可用于一般集合,也可用于独立使用

它使用该类型比较两个表达式是否相等,并根据表达式计算哈希代码

这一切都涉及到访问表达式树,因此,如果您重复执行此操作,成本可能会非常高,但也可能非常方便

该代码可在GPL或

例如,以下是您的测试:

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));
    }
}
使用系统;
使用System.Linq.Expressions;
使用Db4objects.Db4o.Linq.Expressions;
课堂测试{
静态空隙干管()
{
表达式a=x=>false;
表达式b=x=>false;
表达式c=x=>true;
表达式d=x=>x==5;
函数式=
ExpressionEqualityComparer.Instance.Equals;
Console.WriteLine(等式(a,b));
Console.WriteLine(等式(a,c));
Console.WriteLine(等式(a,d));
}
}

它确实会打印真、假、假。

作为一个懒散的答案,您可以检查
ToString()
——它至少应该指出它们明显不同的地方(尽管它会在其中包含var名称,因此必须是相同的)


为了准确地检查等价性。。。更难-需要很多工作,需要很多不同的节点类型。

我在这里问你们:呵呵。但是,是的,我能看出问题所在。。但我也能。。我看不见。因为就像你说的,从技术上来说,他们实际上是平等的。至少我认为一个表达式树应该可以与另一个基于节点和数据类型的表达式树进行比较。在您的示例中,我认为这些表达式是不平等的,因为它们包含对不同对象的引用…numbers1或numbers2将被序列化为ConstantPression节点,其值将不相等。@Jb:表达式可序列化吗?它们的定义不相等,因为它们都引用了闭包中IEnumerable的一个不同实例,而闭包中IEnumerable的实例变成了一个ConstantExpression,其中包含对值属性中RangeEnumerable的引用,并且它们既没有以合理的方式实现Equals,也没有以合理的方式实现GetHashCode。看起来很有希望,但是这些表达式是什么呢(表达式).HashCode?你可以浏览实现,它们在同一个文件夹中。我想我会尝试找到另一种方法来解决我想解决的问题:p但你的答案似乎提供了一个有效的解决方案,所以我将它标记为已接受=)你必须输入大量的代码才能让它工作,例如重新实施ExpressionVisitor:(@JohnNolan,你知道。对于.net 3.5,ExpressionVisitor没有公开,所以你必须自己滚动。对于.net 4.0,这段代码需要更新为新类型的表达式。由于它不是内置的,所以它的工作量很大也就不足为奇了。哈哈,现在这可能实际上是一种工作…:DNo,不是每个表达式都有可用的字符串表示形式。Co例如,nvert没有指明它转换为哪些类型。确切地说,我说过它会找到明显错误的答案,但仅此而已。你需要正确地遍历树,检查实际使用的运算符等,以完成彻底的工作。仍然感谢分享。在一些简单的场景中可能会很好。如果有
MemberInfo
invol在这里,我指的是一些方法,字段的属性,然后你可以先得到memberinfo,然后计算它的散列