"stringDemo" 与 new string("stringDemo".ToCharArray) 的区别。

9
请看下面的代码:
using System;
class MyClass
{
    static void Main()
    {
        object o = ".NET Framework";
        object o1 = new string(".NET Framework".ToCharArray());
        Console.WriteLine(o == o1);
        Console.WriteLine(o.Equals(o1));
    }
}

结果如下:


现在考虑这个:

using System;
class MyClass
{
    static void Main()
    {
        object o = ".NET Framework";
        object o1 = ".NET Framework";
        Console.WriteLine(o == o1);
        Console.WriteLine(o.Equals(o1));
    }
}

执行结果为:
True
True

“==”比较对象引用是否相同,而“.Equals()”比较内容是否相同。我想知道这些代码之间有什么不同?!

object o1 = new string(".NET Framework".ToCharArray());

并且。
object o1 = ".NET Framework"; 

两者都会生成一个对象,但为什么结果不同呢?

5
我想你可能听说过答案中的字符串“interning”,以及字符串是不可变的。 - V4Vendetta
重复的问题:string.Equals()和==运算符真的一样吗?。请先尝试搜索。 - CodeCaster
2
@CodeCaster:不一样...这是关于对象中的字符串,然后进行比较。 - Martin Mulder
@Martin 这与字符串内部化有关,无论您是否将它们装箱为对象。答案在我链接的问题的答案中。 - CodeCaster
与另一篇文章进行比较,这个问题的标题可以是:“object.Equals()和==运算符是否真的相同。” - Martin Mulder
@Martin,就像我说的,装箱并不重要。这与字符串内部有关,正如我链接的问题及其答案所解释的那样。object foo = "bar"并不会使"bar"不再是一个字符串。内部化将导致在编译时相同的字符串引用相同的字符串实例,因此比较它们的引用将显示它们相等。无论您将它们称为字符串还是对象(或其中任何类型,如果有的话),都会发生这种情况。 - CodeCaster
3个回答

15
两个变量都引用同一个字符串常量,因为在C#中,任何两个相等的字符串常量表达式将引用同一个字符串对象。所以o和o1的值是相同的引用。根据C#规范2.4.4节:“当两个或更多按照字符串相等运算符的定义是等效的字符串文字出现在同一程序中时,这些字符串文字引用同一个字符串实例。”如果操作数的编译时类型都是“ string”,则使用由“ string”提供的重载,它执行内容比较;否则,将使用“默认”实现,该实现仅对引用进行相等性比较。在您的情况下,操作数的编译时类型都是“ object”,因此确实使用引用相等性。

这真的回答了他的问题吗?因为他的问题不仅涉及到Equals==,还涉及到objectstring - Martin Mulder
1
@MartinMulder:我认为是这样,因为OP已经意识到“==”比较对象引用是否相同(在他的情况下)。不过我会让这更清晰。 - Jon Skeet

3
也许你会感到困惑,因为你正在使用类型为object而不是string。如果你使用运算符==比较两个object,则仅比较对这些对象的引用。由于在同一个程序集中的两个常量字符串被合并为一个字符串,它们具有相同的引用。如果你要比较两个string,则会使用另一种方法进行操作==。String已经覆盖了==操作符。请参见:http://msdn.microsoft.com/en-us/library/system.string.op_equality(v=vs.110).aspx。此覆盖不比较引用,而是比较两个对象的值。在你的例子中,编译器无法确定两种类型都是string,因为你正在使用objects。这就是为什么string operation ==不用于比较oo1的原因。
回到Equals函数。 Equals是一个可以被继承类重写的函数。在这种情况下,string类已经重写了它,并用自己的比较方法取代它。其中object.Equals仅比较引用,而string.Equals则比较值。 编辑 所以...这将产生你的“奇怪”值:
    object o = ".NET Framework";
    object o1 = new string(".NET Framework".ToCharArray());
    Console.WriteLine(o == o1); // Will prodcuce: False.
    Console.WriteLine(o.Equals(o1)); // Will prodcuce: True.

这将产生预期值:

    string o = ".NET Framework";
    string o1 = new string(".NET Framework".ToCharArray());
    Console.WriteLine(o == o1); // Will prodcuce: True.
    Console.WriteLine(o.Equals(o1)); // Will prodcuce: True.

当我们使用字符串数据类型时,它总是进行内容比较。无论是使用“.Equals()”还是“==”,它都会进行内容比较。 - Masoud Darvishian
@Mesut,但是你没有使用string类型来定义oo1。你使用了object类型。 - Martin Mulder
这是否意味着 string 类型 没有 覆盖 Equals(object) 方法?那么在字典中将其用作键是否会变得危险? - Chris Sinclair
好的... string 确实覆盖了 Equals(object) 方法。这就是为什么你看到的是值比较的结果,而不是引用比较。如果 string 没有覆盖 Equals 方法,那么只会比较引用,结果会是 false。 - Martin Mulder
1
@MartinMulder 哦,天啊。对我来说太早了。完全颠倒了测试结果。以为 == 报告 true,而 Equals 报告 false,所有人都疯了。请忽略我 :) - Chris Sinclair

2

你的第二个示例使用了内部池中的字符串,这就是它们引用相等的原因,而在第一个代码示例中,你有两个不同的字符串对象。考虑以下示例。

object o = ".NET Framework";
object o1 = ".NET Framework";
object o2 = new string(".NET Framework".ToCharArray());
Console.WriteLine(o == o1);
Console.WriteLine(o.Equals(o1));
Console.WriteLine(Object.ReferenceEquals(o,o1)); //True
Console.WriteLine(Object.ReferenceEquals(o, o2)); //False

编辑:

根据其他帖子的评论,我想我应该提到字符串与其他引用类型在使用==时的行为不同:

== 操作符 (C# 参考) - MSDN

对于除了字符串之外的引用类型,如果它的两个操作数指向相同的对象,则==返回true对于字符串类型,==比较字符串的值

因此,以下内容将返回true

string o = ".NET Framework";
string o2 = new string(".NET Framework".ToCharArray());
Console.WriteLine(o == o1); //True

因为现在类型是string,而不是object


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接