Разница между оператором == и методом Equals () в C#?
в чем разница между ==
и Equals()
С примером? Я знаю это ==
используется для сравнения оператор и Equals()
метод используется для сравнения содержимого строки.Поэтому я попытался
// first example
string s1 = "a";
string s2 = "a";
Console.Write(a.Equals(s2)); // returns true, but if I assign "b" to s2,
// then result will be false
// second example
string s1 ="a";
string s2 ="a";
Console.Write(s1 == s2); // returns true
как это так? Оба являются различными ссылками на объекты. Предположим, мы считаем, что это ссылки. Но я пытался использовать вот так
string s1 = new string("ab");
string s2 = new string("ab");
Я получаю ошибку времени компиляции, что не может преобразовать string в char
3 ответов
происходит несколько вещей. Во-первых, в этом примере:
string s1 = "a";
string s2 = "a";
Console.WriteLine(s1 == s2);
вы утверждаете, что:
оба являются различными ссылками на объекты.
это не так из-за интернировании строк. s1
и s2
являются ссылками на один и тот же объект. Спецификация C# гарантирует, что-из раздела 2.4.4.5 спецификации C# 4:
когда два или более строковых литералов, которые эквивалент согласно оператору равенства строк (§7.10.7) появляется в той же программе, эти строковые литералы относятся к тому же экземпляру строки.
таким образом, в этом конкретном случае вы все равно получите "true", даже если вы напечатали object.ReferenceEquals(s1, s2)
, или если вы сделали это использовать сравнение истинной эталонной идентичности с ==
:
object s1 = "a";
object s2 = "a";
Console.WriteLine(s1 == s2); // Still prints True due to string literal interning
однако, даже если эти были ссылки на отдельные объекты, ==
и перегружен для string
. Перегрузка-это времени компиляции решение-реализация для использования зависит от типов времени компиляции операндов. Так например:
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a == b); // Uses string's implementation, prints True
object c = a;
object d = b;
Console.WriteLine(c == d); // Reference identity comparison, prints False
сравните это с object.Equals(object)
который является виртуальным методом. Так уж получилось,String
перегружает этот метод а также, но важно, что он переопределяет его. Так что если мы изменим наш код:
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a.Equals((object) b));
object c = a;
object d = b;
Console.WriteLine(c.Equals(d));
... тогда оба вызова метода в скомпилированном коде будут простоobject.Equals(object)
, но они будут еще оба печатают True из-за полиморфизма: реализация в String
будет использоваться.
вот что такое призыв к перегружен метод будет выглядеть так:
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a.Equals(b)); // Calls string.Equals(string)
цитата из документации равна:
реализация Equals по умолчанию поддерживает ссылочное равенство для ссылочные типы и побитовое равенство для типов значений. Ссылка равенство означает, что сравниваемые ссылки на объекты ссылаются на тот же объект. Побитовое равенство означает, что сравниваемые объекты имеют то же двоичное представление.
и = оператор=:
для предопределенных типов значений, оператор равенства (==) возвращает true, если значения операндов равны, и false в противном случае. Для сравнения типы, отличные от string, = = возвращает true, если его два операнда ссылаются на тот же объект. Для типа string = = сравнивает значения веревка.
теперь вернемся к вашему вопросу: почему s1 == s2
возвращает true? Струны-это особенные звери .Сеть. Они представляют собой неизменяемые ссылочные типы. Они интернированы .Сеть. Это означает, что если у вас есть 2 строковых констант с одинаковым значением, они будут ссылаться на тот же экземпляр объекта во время выполнения.
цитата документация:
среда выполнения common language сохраняет хранилище строк, поддерживая таблица, называемая пулом стажеров, которая содержит одну ссылку на каждая уникальная строка литерала, объявленная или созданная программно в ваша программа. Следовательно, экземпляр литеральной строки с определенное значение существует только один раз в системе.
вы думаете, кажется, Java-esque. На java ==
оператор не может быть настроен, поэтому для ссылочных типов он всегда означает ссылочное равенство, а для примитивных типов-равенство значений. С другой стороны,--1--> для проверки равенства значений в ссылочные типы.
в C# все по-другому. Оба!--1--> и ==
может иметь пользовательские реализации. Разница в том, что Equals
- это виртуальный (экземпляр) метод, в то время как operator==
является статическим методом. Кроме того, они могут вести себя точно так же.
по умолчанию Equals
и ==
проверить равенство ссылок для ссылочных типов, и равенство значений для типов значений. Однако для string
, оба настроены для проверки равенства значений.