运算符'=='不能应用于T型吗?
我认为这个方法是有效的,但我错了:
static void Equals<T>(T x, T y)
{
return x == y; //operator == can't be applied to type T
}
阅读规范后(v3.0中的§7.2.4和v4.0中的§7.3.4):
7.2.4 二元运算符重载解析
x 形式的运算 op y,其中 op 是可重载的 二元运算符,x 是以下表达式 类型 X,y 是类型的表达式 Y,处理如下:
候选用户定义运算符的集合 由 X 和 Y 提供操作 确定算子op(x,y)。这 集合由并集组成 X 和 提供的候选算子 Y 提供的候选算子, 每个都使用以下规则确定 §7.2.5。如果 X 和 Y 是同一类型, 或者如果 X 和 Y 源自 公共基础类型,然后共享 候选运算符仅出现在 组合设置一次。
如果集合 候选用户定义运算符是 不为空,则这成为集合 的候选运营商 手术。否则,预定义的 二元运算符 op 实现, 包括他们举起的形式,成为 的候选算子集合 手术。预定义的 给定运算符的实现 在描述中指定 运营商(§7.7 至 §7.11)。
第 7.4.3 节的重载决议规则应用于候选运算符集合,以选择相对于参数列表 (x, y) 的最佳运算符,并且该运算符成为重载决议的结果过程。如果重载决策无法选择单个最佳运算符,则会发生编译时错误。
在步骤 2 中,我认为应该应用这个预定义的实现:
bool operator ==(object x, object y);
bool operator !=(object x, object y);
因为 C# 中的所有内容都派生自 Object。第3步怎么会出现编译时错误呢?我认为在这种情况下不可能出现“重载解析失败选择”的情况。
编辑 当我实现这样的事情时,我想到了这个问题:
class EnumComparer<TEnum> : IEqualityComparer<TEnum>
{
public bool Equals(TEnum x, TEnum y)
{
return x == y;
}
public int GetHashCode(TEnum obj)
{
return (int)obj;
}
}
恐怕我需要构建一个表达式并在 Equals
方法中动态调用它。
I thought this method was valid but I was wrong:
static void Equals<T>(T x, T y)
{
return x == y; //operator == can't be applied to type T
}
After reading the specifiation (§7.2.4 in v3.0 and §7.3.4 in v4.0):
7.2.4 Binary operator overload resolution
An operation of the form x
op y, where op is an overloadable
binary operator, x is an expression of
type X, and y is an expression of type
Y, is processed as follows:
The set of candidate user-defined operators
provided by X and Y for the operation
operator op(x, y) is determined. The
set consists of the union of the
candidate operators provided by X and
the candidate operators provided by Y,
each determined using the rules of
§7.2.5. If X and Y are the same type,
or if X and Y are derived from a
common base type, then shared
candidate operators only occur in the
combined set once.If the set of
candidate user-defined operators is
not empty, then this becomes the set
of candidate operators for the
operation. Otherwise, the predefined
binary operator op implementations,
including their lifted forms, become
the set of candidate operators for the
operation. The predefined
implementations of a given operator
are specified in the description of
the operator (§7.7 through §7.11).The overload resolution rules of §7.4.3 are applied to the set of candidate operators to select the best operator with respect to the argument list (x, y), and this operator becomes the result of the overload resolution process. If overload resolution fails to select a single best operator, a compile-time error occurs.
In step 2 I think this predefined implementation should be applied:
bool operator ==(object x, object y);
bool operator !=(object x, object y);
since everything in C# derives from Object. How can a compile-time error occurs in step 3? I don't think it's possible that "overload resolution fails to select" in this case.
EDIT The question came to my mind when I was implementing something like this:
class EnumComparer<TEnum> : IEqualityComparer<TEnum>
{
public bool Equals(TEnum x, TEnum y)
{
return x == y;
}
public int GetHashCode(TEnum obj)
{
return (int)obj;
}
}
I'm afraid I need to build a expression and invoke it dynamicly in Equals
method.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
阅读规范对您来说很有好处,但您太早停止阅读了。如果你进一步阅读,你就会明白这一点:
该错误不是来自重载解析;错误是重载解析会选择预定义的引用类型相等运算符,而您没有引用类型。
考虑你的代码。是什么阻止 T 成为未定义相等运算符的值类型?没有什么。假设我们回到对象版本;两个操作数都会装箱到不同的位置,因此引用不相等,即使它们具有相同的内容。由于这种做法缓慢、令人困惑且错误,因此即使尝试也是违法的。
你为什么首先要尝试做这件事?如果您的方法有效,但事实并非如此,那么您的方法将比一开始就简单地使用 == 更糟糕。您打算用这种方法为世界增加什么价值?
(*) 我已向规范维护人员报告了这句话中的语法错误。
Good for you for reading the spec, but you stopped reading too soon. Had you read further you would have gotten to this bit:
The error isn't from overload resolution; the error is that overload resolution would have chosen the predefined reference type equality operator, and you don't have reference types.
Consider your code. What stops T from being a value type with no equality operator defined on it? Nothing. Suppose we fell back to the object version; both operands would box to different locations and therefore be reference-unequal, even if they had the same content. Since that is slow, confusing and wrong, it is illegal to even try.
Why are you trying to do this thing in the first place? If your method worked, which it doesn't, then your method would be worse than simply using == in the first place. What is the value you intend to add to the world with this method?
(*) I've reported the grammatical error in this sentence to the spec maintainers.
如果它知道
where T : class
进行引用比较,那么这可能会起作用。运算符通常对泛型的支持很少,但有一些解决方法。 MiscUtil 为泛型上的运算符提供间接支持,否则EqualityComparer.Default.Equals(x,y)
是一个不错的选择。That would possibly work if it knew that
where T : class
, doing a reference comparison. Operators generally have very little support with generics, but there are workarounds. MiscUtil offers indirect support for operators on generics, otherwiseEqualityComparer<T>.Default.Equals(x,y)
is a good choice.我喜欢使用
EqualityComparer.Default
来实现此目的。它基于重写的
Equals
方法,但在可用时使用IEquatable
,避免对实现它的值类型进行装箱。I like using
EqualityComparer<T>.Default
for this.It is based on the overridden
Equals
method, but usesIEquatable<T>
when available, avoiding boxing on value types implementing it.使用
.Equals()
方法并确保T
实现IComparable
use
.Equals()
method and be sure that theT
implementIComparable