在C#中比较字符串和对象

Meh*_*ani 64 .net c# string

看到这段代码:

object x = "mehdi emrani";
string y = "mehdi emrani";
Console.WriteLine(y == x);
Run Code Online (Sandbox Code Playgroud)

返回true.

但是这段代码:

object x = "mehdi emrani";
string y = "mehdi ";
y += "emrani";
Console.WriteLine(y == x);
Run Code Online (Sandbox Code Playgroud)

回报false.

因此,当我在第一个代码中比较String和Object时,我得到了true.
但是当我在第二个代码中比较它时,我得到了false.

两个字符串都相同,但为什么当我追加到字符串时,我的结果会返回false

Jon*_*eet 91

在每种情况下,第二个操作数==x,是类型的object.这意味着您正在使用普通的引用相等运算符.

现在,在第一种情况下,您使用两个具有相同内容的字符串常量.C#编译器将为这两个引用使用单个对象.在第二种情况下,xy参照不同的字符串对象具有相同的内容.两个引用将是不同的,因此==将返回false.

您可以通过以下方式修复比较:

  • 使用Equals代替-这是重写string(而不是在==这是只有运营商超载:

    Console.WriteLine(y.Equals(x)); // or x.Equals(y), or Equals(y, x)
    
    Run Code Online (Sandbox Code Playgroud)

    Equals(object, object)如果任一参数可以为null,则使用静态方法会很有用; 这意味着你不必担心NullReferenceException.

  • 创建两个类型的变量string,此时将在编译时选择==内部重载string,并且该重载比较字符串的内容,而不仅仅是引用

值得注意的是,这不仅仅是C#编译器注意到字符串文字本身的问题 - 它是关于编译时常量表达式的.例如:

object x = "mehdi emrani";
string y = "mehdi " + "emrani";
Console.WriteLine(y == x); // True
Run Code Online (Sandbox Code Playgroud)

这里y使用两个字符串文字,其初始化是不一样用来初始化一个x,但字符串连接是由编译器,实现了它,它已经用于相同的字符串进行x.

  • 为了更好的对称性并避免"x == null"问题,我更喜欢`Equals(x,y)`而不是`x.Equals(y)`. (2认同)
  • @flindeberg:我避免使用术语实习,因为这通常被视为执行时操作,而这是编译时 - 编译器只会发出单个字符串,因此 CLR 不需要实习任何内容。 (2认同)

Zah*_*med 30

初始化时

object x = "mehdi emrani";  //pointer(x)
Run Code Online (Sandbox Code Playgroud)

它在内存中初始化它并分配对x的引用.在此之后,您初始化

string y = "mehdi emrani"; //pointer(x)
Run Code Online (Sandbox Code Playgroud)

REF

编译器发现该值已经在内存中,因此它为y分配了相同的引用.

现在==,实际比较地址而不是值的相等运算符为两个变量找到相同的地址,结果为true:

x==y  //actually compares pointer(x)==pointer(x) which is true
Run Code Online (Sandbox Code Playgroud)

在第二种情况下,当您初始化x和y时,会分配不同的地址.

object x = "mehdi emrani";  //Pointer(x)
string y = "mehdi ";        //not found in memory
y += "emrani";              //Pointer(y)
Run Code Online (Sandbox Code Playgroud)

现在比较找到导致错误的不同地址:

x == y  //is actually Pointer(x) == Pointer(y) which is false
Run Code Online (Sandbox Code Playgroud)

因此,要克服这一点,您需要使用.Equals()而不是引用来比较值和对象类型.

Console.WriteLine(y.Equals(x));   //compares "mehdi emrani" == "mehdi emrani" results true
Run Code Online (Sandbox Code Playgroud)


Grz*_*nio 7

最有可能的是引用被比较(Equals对象的标准实现).在第一个例子中,C#优化常量字符串,因此y和x实际上指向同一个对象,因此它们的引用是相等的.在另一种情况下,y是动态创建的,因此引用是不同的.


Dav*_*Dev 6

在后台,每次修改现有字符串时都会创建一个新字符串,因为字符串是不可变的,这意味着它们无法更改.

请参阅以下内容以获得解释:为什么.NET String是不可变的?

  • 在我看来,这并没有真正解释发生了什么. (3认同)

Kar*_*ram 6

在第一种情况下,.NET执行字符串常量优化并仅分配一个String实例.x和y都指向同一个对象(两个引用都相等).

但在第二种情况下,x和y指向不同的String实例.将"ermani"添加到y会创建第三个字符串对象.

如果双方的操作数都引用同一个对象,则"=="运算符基本上返回true.在第一种情况下,x和y引用相同的对象,在秒的情况下,x和y引用不同的对象.


i48*_*486 5

你有没有尝试过:

Console.WriteLine(y == x.ToString());
Run Code Online (Sandbox Code Playgroud)

  • @PanagiotisKanavos:这确实可以解决问题,因为编译器知道 `x.ToString` 返回一个字符串,因此它使用重载的 `==` 字符串运算符来比较内容而不是引用。但是,我在这个答案中遗漏了更多细节。 (2认同)