C#中泛型的比较

时间:2018-07-03 15:41:56

标签: c# generics

为什么此代码显示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 个答案:

答案 0 :(得分:3)

来自docs for the == operator

  

对于预定义的值类型,如果相等运算符(==)的操作数相等,则返回true,否则返回false。对于string以外的引用类型,如果==的两个操作数引用同一个对象,则返回true。对于string类型,==比较字符串的值。

由于不能保证T是通用的值类型,因此编译器必须假定它是引用类型。

答案 1 :(得分:2)

我通常会同意您的意见,但您的榜样特别好。

  

我是否正确理解,在进行比较时,它们不是作为字符串而是作为对象进行比较的,这就是为什么不比较它们的值而是它们所指向的地址的原因?

那实际上不是真的。

==文档所述,

  

对于字符串以外的引用类型,如果==的两个操作数引用相同的对象,则返回true。对于string类型,==比较字符串的值。

在您的特定情况下,原因是您在比较它们之前将它们转换为泛型。但是,如果这些是字符串对象,则将比较

答案 2 :(得分:1)

我发现创建一个非通用的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);
    }
}