我不能代表语言设计师,但是从我可以推理的角度来看,这似乎是有意的,适当的设计决策。
查看此基本的F#代码,您可以将其编译为工作库。这是F#的合法代码,仅重载了等于运算符,而不是不等式:
module Module1
type 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,但这不是重点