比较类型的VALUE和REFERENCE

我知道有很多方法可以比较C#中的VALUE和REFERENCES,但是当你尝试比较VALUE或REFERENCE时,我仍然对什么类型执行什么感到困惑。

字符串示例:

string str = "hello"; string str2 = "hello"; if (str == str2) { Console.WriteLine("Something"); } // Is this a comparison of value? if (str.Equals(str2)) { Console.WriteLine("Something"); } // Is this a comparison of value? string.ReferenceEquals(str, str2); // Comparison of reference (True) Console.WriteLine((object)str1 == (object)str2); // Comparison of reference (True) 

如果它们未在子类中重载/重载,则Equals==将默认通过引用进行比较。 ReferenceEquals将始终通过引用进行比较。

字符串是用于实验的一种令人困惑的数据类型,因为它们重载==以实现值相等; 另外,由于它们是不可变的,因此C#通常会为同一个文字字符串重用相同的实例。 在您的代码中, strstr2将是同一个对象。

@Inerdia对他所说的是正确的,但我想指出为什么行string.ferenceEquals(str,str2)在你的代码示例中返回true的原因。 因为您在编译时定义了两个字符串,所以编译器可以优化代码,以便它们都可以指向字符串的同一个实例。 由于字符串是不可变的,因此即使String是引用类型,编译器也知道它可以执行此操作。 但是如果您更改代码以动态生成其中一个字符串(如下所示),则编译器无法执行此优化。 因此,在您的代码示例中,如果您将代码更改为:

 string str = "hello"; string str2 = new StringBuilder().Append("he").Append("llo").ToString(); 

然后string.ReferenceEquals(str,str2)行现在将返回false,因为此时编译器无法重新使用相同的实例(字符串的引用)。

  1. string.ReferenceEquals(str,str2);
    它显然比较了参考文献
  2. str.Equals(STR2)
    试着首先比较参考文献。 然后它尝试按值进行比较。
  3. str == str2
    与Equals相同。

比较字符串的好方法是使用string.Compare。 如果你想忽略大小写,那么也有一个参数。

ReferenceTypes和字符串的平等和比较:

引用类型的工作方式如下:

 System.Object a = new System.Object(); System.Object b = new System.Object(); a == b; //returns true a.Equals(b); //returns false b = a; a == b; //returns true a.Equals(b); //returns true 

由于字符串是引用类型,它们应该做同样的事情,不应该吗? 但他们没有!

C#Documentation定义字符串相等,如下所示:

尽管string是引用类型,但是定义了相等运算符(==和!=)来比较字符串对象的值,而不是引用(7.9.7字符串相等运算符)。 这使得对字符串相等性的测试更加直观。

https://msdn.microsoft.com/en-us/library/362314fe%28v=vs.71%29.aspx https://msdn.microsoft.com/en-us/library/aa664728%28v=vs.71 %29.aspx

这对您测试代码有影响。

 if (str == str2) { Console.WriteLine("Something"); } // This is comparision of value even though string is a referenceType if (str.Equals(str2)) { Console.WriteLine("Something"); } // This is comparion by reference. 

请记住,作为程序员(或者你的狡猾的同事)可以覆盖.Equals(),改变它的行为,你上面看到的是应该发生的事情。 它不一定符合您的代码库 – 现实,如果有疑问,请通过标记.Equals()并点击F12来查看定义。

x.Equals的附录

object.Equals()的行为应该是这些规则:

  • 项目清单
  • x.Equals(x)返回true。
  • x.Equals(y)返回与y.Equals(x)相同的值。
  • if(x.Equals(y)&& y.Equals(z))返回true,然后x.Equals(z)返回true。
  • 只要未修改x和y引用的对象,x.Equals(y)的连续调用就会返回相同的值。
  • x.Equals(null)返回false。 https://msdn.microsoft.com/ru-ru/library/ms173147%28v=vs.80%29.aspx

无论何时您有疑问,都可以调用x.ReferenceEquals,它的定义如下:

与Object.Equals(Object)方法和相等运算符不同,无法覆盖Object.ReferenceEquals(Object)方法。 因此,如果要测试两个对象引用是否相等,并且您不确定Equals方法的实现,则可以调用该方法。

https://msdn.microsoft.com/de-de/library/system.object.referenceequals%28v=vs.110%29.aspx

从而:

 System.Object a = new System.Object(); System.Object b = a; System.Object.ReferenceEquals(a, b); //returns true 

在您的示例中,编译器在优化中合并您的字符串:

 string str = "hello"; string str2 = "hello"; string.ReferenceEquals(str, str2); // Comparison of reference (True) 

在您的示例中,此行为仅适用于编译器优化,如果我们将代码随机化,它将返回false:

 string str = "hello"; string str2 = "hello"; if(throwCoin) { str2 = "bye"; } string.ReferenceEquals(str, str2); // Comparison of reference (False) 

摘自.net来源:

 public bool Equals(string value) { if (this == null) throw new NullReferenceException(); else if (value == null) return false; else if (object.ReferenceEquals((object) this, (object) value)) return true; else return string.EqualsHelper(this, value); } 

所以一般来说,它首先是引用的比较,如果它们不匹配,它会比较值。