栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

为什么我们必须在C#中同时定义==和!=?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

为什么我们必须在C#中同时定义==和!=?

我不能代表语言设计师,但是从我可以推理的角度来看,这似乎是有意的,适当的设计决策。

查看此基本的F#代码,您可以将其编译为工作库。这是F#的合法代码,仅重载了等于运算符,而不是不等式:

module Module1type Foo() =    let mutable myInternalValue = 0    member this.Prop        with get () = myInternalValue        and set (value) = myInternalValue <- value    static member op_Equality (left : Foo, right : Foo) = left.Prop = right.Prop    //static member op_Inequality (left : Foo, right : Foo) = left.Prop <> right.Prop

这确实像它的样子。它仅创建一个相等比较器

==
,并检查该类的内部值是否相等。

虽然无法在C#中创建这样的类,但是 可以 使用为.NET编译的类。显然,它将对我们使用重载运算符。

==
那么,运行时将用于
!=
什么呢?

C#EMCA标准具有一整套规则(第14.9节),解释了如何确定在评估相等性时使用哪个运算符。简而言之,如果要比较的类型是同一类型, 并且
存在重载的相等运算符,它将使用该重载而不是从Object继承的标准引用相等运算符。不足为奇的是,如果只存在一个运算符,它将使用所有对象都具有的默认引用相等运算符,因此不会有任何重载。1个

知道是这种情况,真正的问题是:为什么这样设计,为什么编译器不自行解决?很多人说这不是设计决定,但我想认为是这样设计的,尤其是在所有对象都有默认的相等运算符的情况下。

那么,为什么编译器不能自动创建

!=
运算符呢?除非有Microsoft的确认,否则我无法确定,但这是我根据事实推理所能确定的。


防止意外行为

也许我想做一个值比较

==
来测试相等性。但是,涉及到
!=
我完全不在乎值是否相等,除非引用相等,因为我的程序认为它们相等,所以我只在乎引用是否匹配。毕竟,这实际上被概述为C#的默认行为(如果两个运算符都未重载,例如某些.net库用另一种语言编写的情况)。如果编译器是自动添加代码,那么我将不再依赖编译器来输出应该兼容的代码。编译器不应编写会改变您的行为的隐藏代码,尤其是当您编写的代码在C#和CLI的标准之内时。

关于它 迫使 您重载它,而不是采用默认行为,我只能坚定地说它是标准(EMCA-334 17.9.2)2。该标准未指定原因。我相信这是由于C#从C
++借用了许多行为这一事实。有关更多信息,请参见下文。


当您覆盖
!=
和时
==
,您不必返回bool。

这是另一个可能的原因。在C#中,此函数:

public static int operator ==(MyClass a, MyClass b) { return 0; }

和这个一样有效:

public static bool operator ==(MyClass a, MyClass b) { return true; }

如果返回的不是bool,则编译器 无法 自动推断相反的类型。此外,在您的运算符 确实 返回bool
的情况下,对于他们而言,创建仅在该特定情况下才存在的生成代码,或者如上所述隐藏了CLR缺省行为的代码,这对它们没有意义。


C#从C ++ 3大量借鉴

引入C#时,MSDN杂志上有一篇文章谈到了C#:

许多开发人员希望有一种像Visual Basic一样易于编写,阅读和维护的语言,但仍提供C ++的功能和灵活性。

是的,C#的设计目标是提供与C 几乎相同的功能,只牺牲一点点的便利,例如刚性类型安全性和垃圾回收。C#是在C 之后强烈建模的。

您可能会惊讶地发现,在C ++中, 等于运算符不必返回bool
,如本示例程序所示

现在,C ++不再直接 要求 您重载互补运算符。如果在示例程序中编译了代码,您将看到它运行无误。但是,如果您尝试添加该行:

cout << (a != b);

你会得到

编译器错误C2678(MSVC):二进制’!=’:找不到使用“测试”类型的左操作数(或没有可接受的转换)的运算符。

因此,尽管C 本身不需要成对重载,但它 不会 让您使用尚未在自定义类上重载的相等运算符。它在.NET中有效,因为所有对象都有一个默认对象。C
没有。


1.作为附带说明,如果要重载两个运算符,C#标准仍然要求您重载一对运算符。这是 标准 的一部分,而不仅仅是 编译器
。但是,当您访问以另一种要求不相同的语言编写的.net库时,将采用与确定调用哪个运算符相同的规则。

2. EMCA-334(pdf)(http://www.ecma-international.org/publications/files/ECMA-
ST/Ecma-334.pdf)

3.和Java,但这不是重点



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/506725.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号