Object.Equals是虚拟的,但Object.operator==在C#中不使用它?
我被C#中一个奇怪的“不对称”击中了,我真的不明白。请参阅以下代码:Object.Equals是虚拟的,但Object.operator==在C#中不使用它?,c#,equals,equals-operator,referenceequals,C#,Equals,Equals Operator,Referenceequals,我被C#中一个奇怪的“不对称”击中了,我真的不明白。请参阅以下代码: using System; using System.Diagnostics; namespace EqualsExperiment { class Program { static void Main(string[] args) { object apple = "apple"; object orange = string.F
using System;
using System.Diagnostics;
namespace EqualsExperiment
{
class Program
{
static void Main(string[] args)
{
object apple = "apple";
object orange = string.Format("{0}{1}", "ap", "ple");
Console.WriteLine("1");
Debug.Assert(apple.Equals(orange));
Console.WriteLine("2");
Debug.Assert(apple == orange);
Console.WriteLine("3");
}
}
}
对于所有的.NET专家来说,这可能是显而易见的,但是第二个断言失败了
在Java中,我了解到==是Object.ReferenceEquals的同义词。在C#中,我认为Object.operator==使用Object.Equals,这是虚拟的,因此它在System.String类中被重写
有人能解释一下,为什么第二个断言在C#中失败了?我的哪些假设是错误的?操作符被定义为静态方法,因此它们不能参与多态性。因此,您的第二个断言使用
==
的定义作为对象
(因为您的变量被声明为对象
),它只测试引用相等性。如果变量被声明为string
,则将使用=
字符串的=
重载,第二个断言将成功。运算符=
不是同义词,而是为不同类型定义的运算符
==
操作符是为字符串定义的,然后它实际使用了Equals
方法:
public static bool operator ==(string a, string b) {
return Equals(a, b);
}
但是,在代码中,您没有在字符串上使用运算符,而是在对象上使用运算符,因此您得到的是为对象定义的=
运算符,它使用ReferenceEquals
进行比较
要使用的运算符重载是在编译时决定的,因此决定重载的是变量的类型,而不是变量指向的对象的实际类型。为了完整性,还值得注意的是,在这种情况下,static
object.Equals(apple,orange)
将返回true
object.Equals
首先使用=
检查ref相等,如果失败,它将使用重载的apple.Equals(橙色)
(假设apple
和orange
不是null
)。我知道我使用的是静态bool对象。操作符==(对象,对象)
。但我仍然不明白,为什么不调用Object.Equals(Object)
。由于这是虚拟的,因此将在end.Hmmm中调用正确的String.Equals(Object)
。所以说Object.operator==是用ReferenceEquals定义的,而String.operator==是用Equals定义的。这不是很好,很直观吗?@wigy:大多数情况下,它工作得很好,但当然也有类似于您的示例的情况,您可能希望在运行时确定比较结果。它当然比C++和java中更直观,在这里你不能完全使用字符串上的==运算符。在VB中,=运算符在运行时确定比较,这与VB的工作方式更为一致,但这会导致其他一些情况,让您感到惊讶。在C#中,可以从代码中确定将使用什么样的比较,这更符合C#的一般工作方式。谢谢Guffa。我知道它比C、Java或VB更好。C++操作符可能是虚拟的,因此在那里存在不同的问题。这就是为什么大多数C++编码标准使用YODA条件,比如“代码> >(5=某事物){…} /代码>,从我的答案中,我理解,框架设计者认为引用等价对于一些编码器来说是更直观的,但另一方面,修复了string.operator==的问题。字符串内部处理是否会使==也返回true
?有什么想法吗?@Ani:是的,如果你比较两个具有相同值的插入字符串,它们将指向同一个字符串对象。在OP的例子中,orange
字符串是在运行时故意创建的,这样它就不会被占用。我在另一个线程中发现了一个问题的答案。似乎是对象。运算符=
使用对象。引用等于,但字符串。运算符==
使用对象。等于。这与我的直觉相反,因为object.Equals
是虚拟的,所以它可以在object.operator==
中使用。