Разница между оператором == и методом 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, оба настроены для проверки равенства значений.