4

使用==操作员我可以做到这一点:

int a = 10;
int b = 10;
a==b //true

在这种情况下,C# 做出编译时决定,并且没有虚拟行为发挥作用。

但是,如果我使用:

object a = 10;
object b = 10;
a == b //false

结果是假的,因为object它是一个类(引用类型),a并且b每个都引用堆上不同的装箱对象。

为了解决它,我应该这样做:

object a = 10;
object b = 10;
a.Equals (b) // True

因为Equals是一个虚拟方法,它在运行时根据对象的实际类型解析。

我的问题是:

为什么 C# 的设计者没有通过使 == 虚拟化而在功能上与 Equals 相同来避免这个问题?

4

3 回答 3

12

因为==static方法,所以不能是虚的。这样做可能是为了更好地处理null.

请注意,您的困境与装箱无关,C# 使用两个参数的编译时类型来确定哪些重载*==有意义。例如,举以下例子。

object s1 = "Hello";
object s2 = new String('H', 'e', 'l', 'l', 'o');
s1 == s2; //False
(string)s1 == (string)s2; //True

* 重载不是绝对正确的,因为我们要搜索不止一个类层次结构,但它在语义上足够接近讨论。

于 2012-08-30T17:25:58.577 回答
2

我能想到的一个原因:因为使 == 任何类型的虚拟都会导致继承类的可预测行为显着降低。

class Base {
  public int First;
}

class Derived {
  public int Last;
}

var me = Base{ First = "Alexei" };
var someone = Derived { First = "Alexei", Last = "Unknown" };

现在,如果某种“==”在基类中是虚拟的,并且在派生类中没有被覆盖,那么me == someone这是令人惊讶的。

也不要忘记 C# 不是为 .Net 运行时编译代码的唯一语言,因此对于类似概念可能具有不同语法特征的其他语言,行为应该是合理的。

于 2012-08-30T17:24:53.477 回答
1

a因为那样确定是否和b实际上是同一个对象要困难得多。我们可能想知道这一点。我们特别想知道我们是否通过 type 变量来处理它们object。身份是objectqua的有意义的特征之一object。其他的平等定义不是。

对于引用类型,我们从两者开始==Equals并且GetHashCode只引用身份。ReferenceEquals总是只指身份。

当我们很可能关心将一个类型的两个对象视为等价的其他方式时,我们重写Equals以使用它并GetHashCode进行对应。

当我们不太可能关心身份时,我们==也会忽略。(例如:)string

对于值类型,我们从两者开始==EqualsGetHashCode引用逐个字段的比较,因为这是对值类型具有任何逻辑意义的最具区分性的平等观点。

在处理object变量时,我们很可能关心身份——所以我们有,也很有可能我们关心身份,==所以Equals我们有。很难想出任何不碍事的事情。

于 2012-08-30T17:37:56.117 回答