В случае строк вы, вероятно, не собираетесь использовать равенство ссылок.
Чтобы получить доступ к равенству и неравенству в общих методах, лучше всего сделать это:
EqualityComparer<T>.Default.Equals(x,y); // for equality
Comparer<T>.Default.Compare(x,y); // for inequality
т.е.
static bool AreValuesEqual<T>(T first, T second)
where T : class
{
return EqualityComparer<T>.Default.Equals(first,second);
}
Это все еще использует перегруженный Equals
, но обрабатывает также нули и т. Д. Для неравенства это обрабатывает нули, и оба IComparable<T>
и IComparable
.
Для других операторов см. MiscUtil .
По вопросу; в случае:
string intro1 = "My name is Jon";
string intro2 = "My name is Jon";
Console.WriteLine(intro1 == intro2);
Console.WriteLine(AreReferencesEqual(intro1, intro2));
Вы получаете true
, true
, потому что компилятор и среда выполнения спроектированы так, чтобы быть эффективными со строками; все литералы, которые вы используете, являются «интернированными», и каждый раз в вашем домене приложений используется один и тот же экземпляр. компилятор (а не среда выполнения) также выполняет concat, если это возможно - т.е.
string intro1 = "My name is " + "Jon";
string intro2 = "My name is " + "Jon";
Console.WriteLine(intro1 == intro2);
Console.WriteLine(AreReferencesEqual(intro1, intro2));
- это точно такой же код , как и в предыдущем примере. Там нет никакой разницы вообще. Однако, если вы заставите его объединять строки во время выполнения, он предполагает, что они могут быть недолговечными, поэтому они не интернированы / используются повторно. Итак, по делу:
string name = "Jon";
string intro1 = "My name is " + name;
string intro2 = "My name is " + name;
Console.WriteLine(intro1 == intro2);
Console.WriteLine(AreReferencesEqual(intro1, intro2));
у вас есть 4 строки; «Джон» (интернированный), «Меня зовут» (интернированный) и два разных экземпляра из «Меня зовут Джон». Следовательно, ==
возвращает true, а равенство ссылок возвращает false. Но равенство значений (EqualityComparer<T>.Default
) все равно вернет true.