我知道有很多方法可以比较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)
答案 0 :(得分:4)
Equals
和==
将默认通过引用进行比较。 ReferenceEquals
将始终按引用进行比较。
字符串是一种令人困惑的数据类型,可用于对此进行试验,因为它们会重载==
以实现值相等;另外,由于它们是不可变的,因此C#通常会为同一个文字字符串重用相同的实例。在您的代码中,str
和str2
将是同一个对象。
答案 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)
比较字符串的好方法是使用string.Compare。如果你想忽略大小写,那么也有一个参数。
答案 3 :(得分:1)
参考类型的工作原理如下:
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来查看定义。
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);
}
所以一般来说,首先是引用的比较,如果它们不匹配,它会比较值。