C# 为什么object.Equals和instanceobject.Equals不一样

C# 为什么object.Equals和instanceobject.Equals不一样,c#,string,stringbuilder,C#,String,Stringbuilder,在这里,它返回相同的结果。现在,当我使用StringBuilder时,它不会返回相同的值。背后的原因是什么 string s1 = "t"; string s2 = 't'.ToString(); Console.WriteLine(s1.Equals(s2)); // returning true Console.WriteLine(object.Equals(s1, s2)); // returning tru

在这里,它返回相同的结果。现在,当我使用StringBuilder时,它不会返回相同的值。背后的原因是什么

        string s1 = "t";
        string s2 = 't'.ToString();        

        Console.WriteLine(s1.Equals(s2)); // returning true
        Console.WriteLine(object.Equals(s1, s2)); // returning true
Edit1:我上面的问题回答如下。但在本次讨论中,我们发现StringBuilder的实现中没有任何override Equals方法。所以当我们调用StringBuilder.Equals时,它实际上会转到Object.Equals。因此,如果有人调用StringBuilder.Equals和S1.Equals(S2),结果将不同

比较两个对象的引用,以查看它们对于引用类型(如
StringBuilder
)是否具有引用相等性。对于值类型和
string
的行为类似于值类型(不可变),它会进行逐位比较(确定二进制表示是否相同)。但是,此功能在StringBuilder类中重载

根据,如果两个StringBuilder对象的以下条件相等,StringBuilder的equal方法将返回true:

  • 容量
  • 最大容量
因此,第二个示例中的s1和s2未通过引用相等,但根据刚才提到的标准通过了自定义StringBuilder相等。

在C#中被重写,这样当使用
字符串
上定义的
相等()
重写时,相同的字符串实际上是
相等的(

如果您正在比较(不是示例中的情况),那么值得注意的是相同的字符串文本是。。。也就是说,相同的字符串存在于相同的地址,因此通过引用(例如object.Equals()或s1.ReferenceEquals(s2))以及值也将相等

StringBuilder向以StringBuilder为参数的
Equals()
提供重载(即
s1.Equals(s2)
将调用该重载,而不是调用
object.Equals(object obj)

StringBuilder.Equals()是

如果此实例和sb具有相等的字符串、容量和 最大容量值;否则,错误

object.Equals()使用,它只检查引用的相等性(如果传递了类)或(如果传递了结构)

总而言之

        StringBuilder s1 = new StringBuilder();
        StringBuilder s2 = new StringBuilder();

        Console.WriteLine(s1.Equals(s2)); // returning true
        Console.WriteLine(object.Equals(s1, s2)); // returning false

string类以比较字符串值的方式实现Equals

大多数对象实例,除非它们实现不同类型的比较,否则检查对象引用是否相同


请注意,还有一种情况是,编译器最初将包含完全相同值的两个不同字符串常量分配给同一对象引用。

严格来说,StringBuilder仅重载Equals方法,而不重写virtual object.Equals(object)。这就是两种方法行为不同的原因。我想知道他们是不是忘了在NET1.0中这么做,不想引入突破性的变化?@alexm:很好。我以前没有注意到这一点。更新了我的答案。谢谢埃里克的解释。如果我做一个小的总结:object.Equals将根据输入对象类型检查引用或值。而String和StringBuilder有自己的重载/重写相等方法,该方法将根据其实现工作。如果我错了,请纠正我。我还更新了两个stringbuilder声明,即-stringbuilder s1=new stringbuilder(“abc”,10);StringBuilder s2=新StringBuilder(“abc”,10);那么为什么下面两个实例返回不同的值Console.WriteLine(s1.Equals(s2));//true Console.WriteLine(StringBuilder.Equals(s1,s2));//默认情况下,身份字符串中的假感谢不会被拘留;这很容易用以下代码来证明:
object.ReferenceEquals(新StringBuilder(“abc”).ToString(),新StringBuilder(“abc”).ToString())
(返回false)。但是请注意,C#程序中相同的字符串文字将引用相同的对象。“当根据字符串相等运算符(第7.9.7节)相等的两个或多个字符串文本出现在同一程序集中时,这些字符串文本引用同一个字符串实例。”()字符串不是值类型。(它是一个具有值语义的引用类型。)@BradleyGrainger,我知道从技术上讲它不是一个值类型,但在本例中,它的作用是相同的。不过我会更新我的答案来澄清。谢谢,接得好!总之,
StringBuilder
似乎忘记覆盖
Equals(object)
。让
Equals(StringBuilder)
具有与
Equals(object)
不同的行为似乎是违反直觉的。
string s1 = "t";
string s2 = 't'.ToString();        

Console.WriteLine(s1.Equals(s2)); // true because both reference equality (interned strings) and value equality (string overrides Equals())
Console.WriteLine(object.Equals(s1, s2)); // true because of reference equality (interned strings)

StringBuilder s1 = new StringBuilder();
StringBuilder s2 = new StringBuilder();

Console.WriteLine(s1.Equals(s2)); // true because StringBuilder.Equals() overloaded
Console.WriteLine(object.Equals(s1, s2)); // false because the two StringBuilder instances have different addresses (references not equal)