【发布时间】:2020-01-31 21:21:21
【问题描述】:
在运行时使用表达式树编译代码时,我们可能会发现自己需要检查不确定类型的对象是否相等。
如果我们只是为每种情况手动编写代码,编译器会为我们考虑很多事情。想到的最多的是:
- 如果通用重载
T1.Equals<T2>或T2.Equals<T1>可用,则使用它。 - 否则,如果任一类型有一个隐式运算符可以让我们应用 (1),则使用该运算符。
- 否则,将使用
bool Equals(object)(当然要考虑潜在的覆盖)。
很遗憾,Expression.Equal(Expression left, Expression right) 并没有为我们做所有这些事情。
我们如何才能实现编译器通常提供的相同行为?
【问题讨论】:
-
您必须阅读规范并自己实施所有这些检查/搜索。据我所知,没有什么是公开可见的——
dynamic正是这样做的——你可能想了解它是如何完成的。 (我不确定该代码是否公开可用) -
使用表达式树,您只能创建一个方法,为了您的目标,您需要实现整个类。要么使用需要 Know-How 的 TypeBuilder,要么生成 C# 源代码文件并编译,这样更容易但速度稍慢。
-
从好的方面来说,我意识到通常两种情况之一适用。 (A) 类型是结构体,为了避免装箱,使用
Equals(T)接口发出信号的通用Equals(T)重载是有好处的。 (B) 类型是一个类。如果有直接的IEquatable<T>接口,我们可以使用它。如果只有 base 类型在其自身上实现IEquatable<T>,编译器通常仍会选择它,但我们的实现找不到它。幸运的是,这无关紧要:Equals(object)应该始终返回与Equals(T)相同的结果,用于T参数。 -
我应该注意到我之前的评论部分适用于 我只是比较相同编译时类型的对象。如果不是这种情况,
Equals调用的操作数通常可能会被编译器隐式转换,这会使在运行时执行相同操作的实现变得复杂。
标签: c# expression equals expression-trees overload-resolution