比较类型的VALUE和REFERENCE

本文关键字:REFERENCE VALUE 类型 比较 | 更新日期: 2023-09-27 18:11:56

我知道在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)

比较类型的VALUE和REFERENCE

Equals==如果在子类中没有被重写/重载,默认情况下将通过引用进行比较。ReferenceEquals总是通过引用进行比较。

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

@ indidia说的是对的,但我想指出为什么行字符串。在代码示例中,ReferenceEquals(str, str2)返回true。因为您在编译时定义了这两个字符串,所以编译器可以优化代码,使它们都指向字符串的相同实例。因为字符串是不可变的,编译器知道它可以这样做,即使字符串是一个引用类型。但是,如果您更改代码以动态生成其中一个字符串(如下所示),编译器将无法执行此优化。所以在你的代码示例中如果你把代码改成:

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

然后是字符串。ReferenceEquals(str, str2)行现在将返回false,因为这次编译器不知道重用相同的实例(字符串的引用)。

参考类型和字符串的相等性和比较:

引用类型是这样工作的:

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#文档像这样定义字符串相等性:

虽然string是引用类型,但是相等操作符(==和!=)的定义是为了比较字符串对象的值,而不是引用(7.9.7字符串相等操作符)。这使得测试字符串相等更直观。

https://msdn.microsoft.com/en-us/library/362314fe%28v=vs.71%29.aspxhttps://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 = (y) &&y.Equals(z))返回true,然后x.Equals(z)返回true。
  • x = equals (y)的连续调用返回相同的值,只要x和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)
  1. 字符串。
    它显然比较引用。
  2. str.Equals(str2)
    首先尝试比较引用。然后它尝试按值进行比较。
  3. 节选自。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);
    }
    

    一般来说,首先比较引用,如果它们不匹配,则比较值