比较类型的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)
Equals
和==
如果在子类中没有被重写/重载,默认情况下将通过引用进行比较。ReferenceEquals
总是通过引用进行比较。
字符串是一种令人困惑的数据类型,因为它们重载==
来实现值相等;此外,由于它们是不可变的,c#通常会为相同的字面值字符串重用相同的实例。在您的代码中,str
和str2
将是同一个对象。
@ 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)
- 字符串。
它显然比较引用。 - str.Equals(str2)
首先尝试比较引用。然后它尝试按值进行比较。
节选自。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);
}
一般来说,首先比较引用,如果它们不匹配,则比较值