Равенство и сравнение эталонных типов и строк:
Типы ссылок работают следующим образом:
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 # Документация определяет равенство строк следующим образом:
Хотя строка является ссылочным типом, операторы равенства (== и
! =) определены для сравнения значений строковых объектов, а не
ссылки (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
Поведение объекта. Эквалайзеры () должны эти правила:
- Элемент списка
- x.Equals (x) возвращает true.
- x.Equals (y) возвращает то же значение, что и y.Equals (x).
- если (x.Equals (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)