C# 隐式转换和 == 运算符
Posted
技术标签:
【中文标题】C# 隐式转换和 == 运算符【英文标题】:C# implicit conversions and == operator 【发布时间】:2010-10-27 21:08:50 【问题描述】:一些上下文代码:
class a
class b
public a aget;set;
public static implicit operator a(b b)
return b.a;
a a=null;
b b=null;
a = b;
//compiler: cannot apply operator '==' to operands of type tralala...
bool c = a == b;
是否可以在不同类型的实例上使用 == 运算符,其中一个可以隐式转换为另一个?我错过了什么?
编辑: 如果类型必须是相同的调用==,那为什么
int a=1;
double b=1;
bool c=a==b;
有效吗?
【问题讨论】:
我假设您的 int/double 示例有效,因为它们是值类型,而不是引用类型... 这可能是一个原因。唯一的问题是 - 如果是这样,它并不能解释为什么引用类型不能像值类型一样隐式执行转换。 【参考方案1】:implicit
运算符仅适用于赋值。
您想重载相等 (==
) 运算符,如下所示:
class a
public static bool operator ==(a x, b y)
return x == y.a;
public static bool operator !=(a x, b y)
return !(x == y);
class b
public a aget;set;
public static implicit operator a(b b)
return b.a;
这应该允许您按照帖子中的建议比较 a
和 b
类型的两个对象。
var x = new a();
var y = new b();
bool c = (x == y); // compiles
注意:
我建议简单地覆盖 GetHashCode
和 Equals
方法,正如编译器警告的那样,但由于您似乎想要抑制它们,您可以按如下方式进行。
将a
的类声明更改为:
#pragma warning disable 0660, 0661
class a
#pragma warning restore 0660, 0661
// ...
【讨论】:
在这种情况下,a == b 表达式将毫无问题地编译。 这似乎是正确的答案。有点想通了。只是 - 我认为在这种情况下运算符重载将是矫枉过正(它也需要 gethash() 和 equals() 函数重载:/)。 是的,在用户定义的类型上定义或使用自定义(重载)运算符没有任何限制。 @Arnis L:幸运的是,它们只是警告。如果您愿意,您可以覆盖它们(Equals 可以具有与 == 相同的逻辑,并且 GetHashCode 可以只返回 a.GetHashCode() ^ b.GetHashCode()),或者如果您不在乎,您可以忽略/抑制警告。 哦,对了,我错过了你的那一点问题,抱歉。我相信这是一个特定于编译器的功能(在 System.Int32 或 System.Double 中没有定义运算符重载)。在这种情况下,b(双精度)在等同于相同类型的对象之前被转换为 int。 (它可能反过来 - 一个简单的测试会告诉你。)希望这一切现在对你有意义。【参考方案2】:是否可以使用 == 运算符 不同类型的实例,其中一个 可以隐式转换为另一个?
是的。
我错过了什么?
这是规范的相关部分。您错过了突出显示的单词。
预定义的引用类型相等 运算符要求 [that] 两个操作数 是引用类型值或 字面量为空。此外,标准 隐式转换存在于 任一操作数的类型 另一个操作数。
根据定义,用户定义的转换不是标准转换。这些是引用类型。因此,预定义的引用类型相等运算符不是候选对象。
如果类型必须相同,则调用 ==, 那么为什么 [double == int] 有效?
您认为类型必须相同的假设是不正确的。有一个从 int 到 double 的标准隐式转换,并且有一个相等运算符需要两个双精度,所以这是可行的。
我想你也错过了这一点:
使用 预定义的引用类型相等 运算符比较两个引用 已知在 编译时。例如,如果 操作数的编译时类型是 两个类类型 A 和 B,如果 A 和 B 都不是从 其他,那么就不可能 引用相同的两个操作数 目的。因此,操作是 认为是编译时错误。
【讨论】:
【参考方案3】:我想你需要为你感兴趣的类型实际覆盖 == 运算符。即使类型是隐式可转换的,编译/运行时是否仍然会抱怨是你必须尝试的事情。
public static bool operator ==(a a, b b)
//Need this check or we can't do obj == null in our Equals implementation
if (((Object)a) == null)
return false;
else
return a.Equals(b);
或者只使用 ole6ka 建议的 Equals 实现,并确保该实现执行您需要的类型转换。
【讨论】:
【参考方案4】:http://msdn.microsoft.com/en-us/library/8edha89s.aspx
在每种情况下,必须有一个参数 与类或结构相同的类型 声明运算符 (...)
【讨论】:
【参考方案5】:使用这个
bool c = a.Equals(b);
【讨论】:
这在特定情况下没有用,因为我正在滥用 lambdas 和构建器模式来创建动态属性设置器,如下所示: factory.Object.With(object=>object.MyProp==newPropValue ).Create()以上是关于C# 隐式转换和 == 运算符的主要内容,如果未能解决你的问题,请参考以下文章