Сравнение дженериков в C#
почему этот код печатает False?
class Program
{
public static void OpTest<T>(T s, T t) where T : class
{
Console.WriteLine(s == t);
}
static void Main()
{
string s1 = "string";
System.Text.StringBuilder sb = new System.Text.StringBuilder(s1);
string s2 = sb.ToString();
OpTest(s1, s2);
}
}
3 ответов
для предопределенных типов значений, оператор равенства (
==
) возвращаетtrue
Если значения операндов равны,false
иначе. Для ссылочных типов, отличных отstring
,==
возвращаетtrue
если два операнда указывают на один объект. Дляstring
тип,==
сравнивает значения строк.
С T
не может быть гарантированно тип значения как универсальный, компилятор должен предположить, что это ссылочный тип.
Я бы и согласен с вами в комментариях, но ваш пример особенно хорош.
правильно ли я понимаю, что при сравнении они сравниваются не как строки, а как объекты, поэтому сравниваются не их значения, а адреса, на которые они указывают?
это на самом деле не так.
как говорится в ==
документация
для справочных типов, отличных от строке
==
возвращает true, если два операнда указывают на один объект. Дляstring
тип,==
сравнивает значения строк.
в вашем конкретном случае причина в том, что вы бросаете их как дженерики, прежде чем сравнивать их. Но если это были объекты string, то стоимостью будет сравнивать.
Я считаю полезным создать неродовой OpTest
метод для подтверждения того, что происходит. Универсальный метод обрабатывает параметры как Object
типы и не использовать ==
перегрузка String
, что является частным случаем для сравнения значений.
в обоих случаях параметры типа String
но общий метод рассматривает их "обобщенно" при проведении сравнения.
void Main()
{
string s1 = "string";
System.Text.StringBuilder sb = new System.Text.StringBuilder(s1);
string s2 = sb.ToString();
TestClass.OpTest(s1, s2);
TestClass.OpTest<string>(s1, s2);
// OpTest: s is System.String, t is System.String
// True
// OpTest<T>: s is System.String, t is System.String
// False
}
public class TestClass
{
public static void OpTest(string s, string t)
{
Console.WriteLine($"OpTest: s is {s.GetType()}, t is {t.GetType()}");
// Uses String's == operator, which compares the values
Console.WriteLine(s == t);
}
public static void OpTest<T>(T s, T t) where T : class
{
Console.WriteLine($"OpTest<T>: s is {s.GetType()}, t is {t.GetType()}");
// Uses Object's == operator, which is a reference comparison
Console.WriteLine(s == t);
}
}