简体   繁体   English

C#中泛型的比较

[英]Comparison of Generics in C#

Why does this code prints 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);
    }
}

Do I understand correctly that when compared, they are compared not as strings, but as objects, which is why not their values are compared, but the addresses to which they point? 我是否正确理解,比较时,它们不是作为字符串进行比较,而是作为对象进行比较,这就是为什么不比较它们的值,而是它们指向的地址?

From the docs for the == operator : ==运算符文档

For predefined value types, the equality operator ( == ) returns true if the values of its operands are equal, false otherwise. 对于预定义的值类型,如果操作数的值相等,则相等运算符( == )返回true ,否则返回false For reference types other than string , == returns true if its two operands refer to the same object. 对于除string之外的引用类型,如果其两个操作数引用同一对象,则==返回true For the string type, == compares the values of the strings. 对于string类型, ==比较string的值。

Since T cannot be guaranteed to be a value type as it's generic, the compiler must assume it is a reference type. 由于T不能保证是值类型,因为它是通用的,因此编译器必须假定它是引用类型。

I would normally go and agree with you in the comments, but your example is especially good. 我通常会在评论中同意你,但你的例子特别好。

Do I understand correctly that when compared, they are compared not as strings, but as objects, which is why not their values are compared, but the addresses to which they point? 我是否正确理解,比较时,它们不是作为字符串进行比较,而是作为对象进行比较,这就是为什么不比较它们的值,而是它们指向的地址?

That is actually not true. 实际上并非如此。

As stated in the == documentation, ==文档中所述,

For reference types other than string, == returns true if its two operands refer to the same object. 对于除string之外的引用类型,如果其两个操作数引用同一对象,则==返回true。 For the string type, == compares the values of the strings. 对于string类型, ==比较string的值。

In your particular case, the reason is you're casting them as generics before comparing them. 在您的特定情况下,原因是您在比较它们之前将它们作为泛型。 But if those were string objects, the value would be compared. 但如果这些是字符串对象,则会比较该

I find it helpful to create a non-generic OpTest method to confirm what's happening. 我发现创建一个非通用的OpTest方法来确认发生了什么是有帮助的。 The generic method treats the parameters as Object types and does not use the == overload for String , which is a special case to compare the values. 泛型方法将参数视为Object类型,并且不对String使用==重载,这是比较值的特殊情况。

In both cases the parameters are type String but the generic method treats them "generically" when making the comparison. 在这两种情况下,参数都是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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM