为什么StringBuilder.Equals在这种情况下返回“true”?

时间:2014-07-22 00:55:25

标签: c# string equals stringbuilder equals-operator

我在比较C#(XNA)中的两个StringBuilder时遇到了一个小问题。

StringBuilder sb1;
StringBuilder sb2;

两者都在我的代码的不同部分初始化。一个简单的Console.WriteLine显示它们包含相同的文本。但是,以下是错误的:

sb1.Equals(sb2); // This is false

然而以下是真的

sb1.ToString().Equals(sb2.ToString); // This is true

怎么会发生这种情况?

2 个答案:

答案 0 :(得分:7)

由于string类会覆盖Equals方法,因此字符串会按值而不是引用进行比较。

请参阅documentation

  

尽管string是引用类型,但是定义了相等运算符(==和!=)来比较字符串对象的值,而不是引用。

它讨论了==!=运算符,但实际上它们正在调用string.Equals并且它按值比较字符串。

答案 1 :(得分:3)

Equals上有两个StringBuilder重载,可以做一些意想不到的事情。

Equals(Object)重载继承自Object并比较引用。

Equals(StringBuilder)重载比较内容,容量和MaxCapacity

你似乎在调用这两个重载中的第二个。

由于StringBuilder将动态扩展其容量,因此比较两个StringBuilder实例的结果取决于对每个实例执行的操作的确切顺序(例如,追加,替换,删除等)。

例如,这会给出您描述的结果:

StringBuilder sb1 = new StringBuilder(), sb2 = new StringBuilder();
sb1.Append("something").Append('1', 100).Replace("1", "");
sb2.Append("something");
Console.WriteLine(sb1.Equals(sb2)); // False
Console.WriteLine(sb1.ToString().Equals(sb2.ToString())); // True

似乎没有内置方式来比较内容,但如果您不想在比较时分配字符串,则可以轻松编写自己的比较:

public static bool Equals(StrinBuilder left, StringBuilder right)
{
    if (left.Length != right.Length)
        return false;

    int length = left.Length;
    for(int i = 0; i < length; i++)
        if (left[i] != right[i])
            return false;

    return true;
}