为什么C#允许将对象隐式转换为int以进行相等性比较,而不是对象类型与对象类型比较,即使存在隐式运算符?
bool errorHere = valueOnly == valuePair;
行在底部给出了异常。
class Program
{
static void Main(string[] args)
{
ValueOnly valueOnly = new ValueOnly();
ValuePair valuePair = new ValuePair();
bool areEqual = valueOnly.Value == valuePair;
bool errorHere = valueOnly == valuePair;
bool butNotHere = valueOnly == (ValueOnly)valuePair;
valueOnly = valuePair; // Or Here
}
}
public class ValuePair
{
public int Value { get; set; }
public string Text { get; set; }
public static implicit operator ValueOnly(ValuePair valuePair) {
if (valuePair.Text != null || valuePair.Value != 0) {
return new ValueOnly() { Value = valuePair.Value };
}
return null;
}
public static implicit operator int(ValuePair valuePair) {
return valuePair.Value;
}
}
public class ValueOnly
{
public int Value { get; set; }
}
这是错误:
Error Operator '==' cannot be applied to operands of type 'ValueOnly' and 'ValuePair'
答案 0 :(得分:1)
C#当然不允许出于任何目的将对象隐式转换为int
。我不确定你是否指的是
bool butNotHere = valueOnly == (ValueOnly)valuePair;
作为“允许”这样的转换。如果是这样,它就不会做任何这样的事情。它只是调用你自己的转换操作符(如果我正确读取代码将返回null
,因为该值将是一个默认构造的整数),然后在两个对象之间进行引用比较(其值为{{1因为false
不是引用 - 等于任何东西)。
不言而喻,一旦定义了隐式转换运算符,C#将在必要时使用它。因此,我认为你的问题必须更多地理解等于运算符如何基于其参数的类型而不是其他任何东西。
更新,关于null
支票:
C#规范,7.10.6(引用类型相等运算符)状态:
使用预定义的引用类型是绑定时错误 等于运算符来比较已知的两个引用 在绑定时不同。例如,如果绑定时间类型 操作数是两种类型A和B,如果既不是A也不是B. 来自另一方,那么这两者是不可能的 操作数引用同一个对象。因此,操作是 被视为绑定时错误。
如果您希望能够比较类类型的对象是否相等,最好的方法是实现valueOnly == valuePair
接口,并覆盖IEquatable<T>
以object.Equals
方式实现(这意味着您还必须覆盖IEquatable<T>.Equals
)才能匹配。
然而,在比较项目时依赖“隐藏”转换是个坏主意。如果我们在谈论比较不相关的课程,那么通过尽可能突出比较,你将为自己节省很多痛苦。为此,我建议低技术
object.GetHashCode
答案 1 :(得分:0)
要允许valueOnly == valuePair,您必须将其添加到ValuePair类:
public static bool operator == (ValueOnly valueOnly, ValuePair valuePair){
ValueOnly value = valuePair;
return valueOnly.Value == value.Value;
}
这使用隐式转换,然后执行我正在寻找的等式检查...
现在我想起来了,隐式转换是愚蠢的(因为我没有为ValueOnly类提供相等运算符):
public static bool operator == (ValueOnly valueOnly, ValuePair valuePair){
return valueOnly.Value == valuePair.Value;
}