Зачем использовать String.Equals над ==?

Недавно я познакомился с большой базой кода и заметил, что все сравнения строк выполняются с помощью String.Equals() вместо ==

Какова причина этого, как вы думаете?

Ответ 1

Весьма вероятно, что большая часть базы разработчика основана на фоне Java, где использование == для сравнения строк неверно и не работает.

В С# нет (практической) разницы (для строк), пока они набираются как строка.

Если они напечатаны как object или T, то см. другие ответы здесь, в которых рассказывается об общих методах или перегрузке оператора, так как там определенно хотите использовать метод Equals.

Ответ 2

Существует практическая разница между string.Equals и ==

bool result = false;

object obj = "String";    
string str2 = "String";
string str3 = typeof(string).Name;
string str4 = "String";
object obj2 = str3;

// Comparision between object obj and string str2 -- Com 1
result = string.Equals(obj, str2);// true
result = String.ReferenceEquals(obj, str2); // true
result = (obj == str2);// true

// Comparision between object obj and string str3 -- Com 2
result = string.Equals(obj, str3);// true
result = String.ReferenceEquals(obj, str3); // false
result = (obj == str3);// false

// Comparision between object obj and string str4 -- Com 3
result = string.Equals(obj, str4);// true
result = String.ReferenceEquals(obj, str4); // true
result = (obj == str4);// true

// Comparision between string str2 and string str3 -- Com 4
result = string.Equals(str2, str3);// true
result = String.ReferenceEquals(str2, str3); // false
result = (str2 == str3);// true

// Comparision between string str2 and string str4 -- Com 5
result = string.Equals(str2, str4);// true
result = String.ReferenceEquals(str2, str4); // true
result = (str2 == str4);// true

// Comparision between string str3 and string str4 -- Com 6
result = string.Equals(str3, str4);// true
result = String.ReferenceEquals(str3, str4); // false
result = (str3 == str4);// true

// Comparision between object obj and object obj2 -- Com 7
result = String.Equals(obj, obj2);// true
result = String.ReferenceEquals(obj, obj2); // false
result = (obj == obj2);// false

Добавление часов

obj     "String" {1#}   object {string}
str2    "String" {1#}   string
str3    "String" {5#}   string
str4    "String" {1#}   string
obj2    "String" {5#}   object {string}

Теперь посмотрите {1#} и {5#}

obj, str2, str4 и obj2 ссылки одинаковы.

obj и obj2 являются object type, а другие - string type

Заключение:

  • com1: result = (obj == str2);//true
    • сравнивает object и string, поэтому выполняет проверку равенства ссылок
    • obj и str2 указывают на одну и ту же ссылку, поэтому результат верен.
  • com2: result = (obj == str3);//false
    • сравнивает object и string, поэтому выполняет проверку равенства ссылок
    • obj и str3 указывают на разные ссылки, поэтому результат ложный
  • com3: result = (obj == str4);//true
    • сравнивает object и string, поэтому выполняет проверку равенства ссылок
    • obj и str4 указывают на одну и ту же ссылку, поэтому результат верен.
  • com4: result = (str2 == str3);//true
    • сравнивает string и string, поэтому выполняет проверку значения строки
    • str2 и str3 являются "String" , поэтому результат верен.
  • com5: result = (str2 == str4);//true
    • сравнивает string и string, поэтому выполняет проверку значения строки
    • str2 и str4 являются "String" , поэтому результат верен.
  • com6: result = (str3 == str4);//true
    • сравнивает string и string, поэтому выполняет проверку значения строки
    • str3 и str4 являются "String" , поэтому результат верен.
  • com7: result = (obj == obj2);//false - сравнивает object и object, поэтому выполняет контрольную проверку равенства - obj и obj2 указывают на разные ссылки, поэтому результат ложный

Ответ 3

Существует одна тонкая, но очень важная разница между == и методами String.Equals:

class Program
{
    static void Main(string[] args)
    {
        CheckEquality("a", "a");
        Console.WriteLine("----------");
        CheckEquality("a", "ba".Substring(1));
    }

    static void CheckEquality<T>(T value1, T value2) where T : class
    {
        Console.WriteLine("value1: {0}", value1);
        Console.WriteLine("value2: {0}", value2);

        Console.WriteLine("value1 == value2:      {0}", value1 == value2);
        Console.WriteLine("value1.Equals(value2): {0}", value1.Equals(value2));

        if (typeof(T).IsEquivalentTo(typeof(string)))
        {
            string string1 = (string)(object)value1;
            string string2 = (string)(object)value2;
            Console.WriteLine("string1 == string2:    {0}", string1 == string2);
        }
    }
}

Производит этот вывод:

value1: a
value2: a
value1 == value2:      True
value1.Equals(value2): True
string1 == string2:    True
----------
value1: a
value2: a
value1 == value2:      False
value1.Equals(value2): True
string1 == string2:    True

Вы можете видеть, что оператор == возвращает false для двух явно равных строк. Зачем? Поскольку оператор ==, используемый в общем методе, разрешен как метод op_equal, как определено System.Object(единственная гарантия T, которая имеет метод во время компиляции), что означает, что он ссылается на равенство вместо равенства значений.

Если у вас два значения, введенные как System.String явно, тогда == имеет семантику равенства по значению, потому что компилятор разрешает == для System.String.op_equal вместо System.Object.op_equal.

Итак, чтобы играть в это безопасно, я почти всегда использую String.Equals вместо этого, я всегда получаю семантику равенства значений, которую я хочу.

И чтобы избежать NullReferenceExceptions, если одно из значений равно null, я всегда использую статический метод String.Equals:

bool true = String.Equals("a", "ba".Substring(1));

Ответ 4

String.Equals предлагает перегрузки для обработки обсадной колонны и сравнения с культурой. Если ваш код не использует их, разработчики могут просто использоваться для Java, где (как говорит Мэтью), вы должны использовать метод .Equals для сравнения контента.

Ответ 5

Оба метода выполняют ту же функциональность - для сравнения значений. Как написано в MSDN:

  • О методе String.Equals - определяет, будет ли этот экземпляр и другой заданный объект String имеет одинаковое значение. (http://msdn.microsoft.com/en-us/library/858x0yyx.aspx)
  • О '==' - Хотя строка является ссылочным типом, операторы равенства (== и ! =) определены для сравнения значений строковых объектов, а не Рекомендации. Это делает тестирование для равенства строк более интуитивным. (http://msdn.microsoft.com/en-en/library/362314fe.aspx)

Но если один из ваших экземпляров строк равен NULL, эти методы работают по-разному:

        string x = null;
        string y = "qq";
        if (x == y) // returns false
            MessageBox.Show("true");
        else
            MessageBox.Show("false");

        if (x.Equals(y)) // returns System.NullReferenceException: Object reference not set to an instance of an object. - because x is null !!!
            MessageBox.Show("true");
        else
            MessageBox.Show("false");

Ответ 6

Там написано о этой статье, которое может показаться интересным, с некоторыми цитатами из Jon Skeet. Похоже, что использование почти то же самое.

Jon Skeet утверждает, что производительность экземпляра Equals "немного лучше, когда строки коротки - по мере увеличения длины строк, эта разница становится совершенно несущественной".

Ответ 7

Я хочу добавить, что есть другая разница. Это связано с тем, что говорит Эндрю.

Это также связано с ОЧЕНЬ раздражающим, чтобы найти ошибку в нашем программном обеспечении. См. Следующий упрощенный пример (я также пропустил нулевую проверку).

public const int SPECIAL_NUMBER = 213;

public bool IsSpecialNumberEntered(string numberTextBoxTextValue)
{
    return numberTextBoxTextValue.Equals(SPECIAL_NUMBER)
}

Это будет компилировать и всегда возвращать false. Хотя следующее приведет к ошибке компиляции:

public const int SPECIAL_NUMBER = 213;

public bool IsSpecialNumberEntered(string numberTextBoxTextValue)
{
    return (numberTextBoxTextValue == SPECIAL_NUMBER);
}

Нам пришлось решить аналогичную проблему, когда кто-то сравнивал перечисления разного типа с помощью Equals. Вы будете читать это МНОГО раз, прежде чем осознать, что это причина ошибки. Особенно, если определение SPECIAL_NUMBER не находится вблизи проблемной области.

Вот почему я действительно против использования Equals в ситуациях, когда это не обязательно. Вы теряете немного безопасности типов.

Ответ 8

Я только что ударился головой о стену, пытаясь решить проблему, потому что я прочитал эту страницу и пришел к выводу, что на практике нет существенной разницы, когда на практике есть, поэтому я отправлю эту ссылку здесь, если кто-то еще найдет их получить разные результаты из == и равно.

Объект == равенство не выполняется, но .Equals преуспевает. Это имеет смысл?

string a = "x";
string b = new String(new []{'x'});

Console.WriteLine("x == x " + (a == b));//True
Console.WriteLine("object x == x " + ((object)a == (object)b));//False
Console.WriteLine("x equals x " + (a.Equals(b)));//True
Console.WriteLine("object x equals x " + (((object)a).Equals((object)b)));//True