我正在考虑使用Linq Expression作为字典中的键。但是,我担心我会得到奇怪的结果,因为我不知道Linq表达式如何确定Equality。
派生自Expression的类是否比较值相等或引用相等?或者换句话说,
Expression<Func<object>> first = () => new object();
Expression<Func<object>> second = ()=>new object();
bool AreTheyEqual = first == second;
你的测试比较 表达式。表达本身只提供参考平等;你的测试可能会显示“假”。为了脸颊 语义 你需要做大量工作的平等 - 例如:
x => 123
和
y => 123
当量?作为原始测试,您可以比较ToString(),但这将非常脆弱。
比较任何非值类型的对象(包括表达式)与==比较对象引用,因此它们将不相等。然而,正如一位评论者指出的那样,字典会被使用 Equals
和 GetHashCode
确定平等,这仍然默认最终确定它们不相等。
您可以创建一个继承的类 System.Linq.Expression
和覆盖 GetHashCode
和 Equals
但是,以某种方式使用结果,并将其用作词典的关键字。
正如其他人所指出的,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