比较类型的VALUE和REFERENCE

时间:2011-10-19 12:37:25

标签: c# types comparison equals equals-operator

我知道有很多方法可以比较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)

5 个答案:

答案 0 :(得分:4)

如果它们未在子类中重载/重载,则

Equals==将默认通过引用进行比较。 ReferenceEquals将始终按引用进行比较。

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

答案 1 :(得分:2)

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

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

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

答案 2 :(得分:1)

  1. string.ReferenceEquals(str,str2);
    它显然比较了参考文献。
  2. str.Equals(str2)
    试着首先比较参考文献。然后它尝试按值进行比较。
  3. str == str2
    和Equals一样。
  4. 比较字符串的好方法是使用string.Compare。如果你想忽略大小写,那么也有一个参数。

答案 3 :(得分:1)

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 comparison by value too, because Equals is overrided in String class.

请记住,作为程序员(或者你的狡猾的同事),你可以覆盖.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)

答案 4 :(得分:0)

摘自.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);
}

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