简体   繁体   中英

How does C# compiler determine reference equality in generic methods when operator overloads for a specified type exists?

Currently going through Jon Skeet's "C# In Depth, 3rd edition" and I have a small question concerning reference equality. For those interested, the following code is a small variation of Jon's code from Chptr 3. p.80:

Public Function stored in a class; note that 'T' is constrained to reference types:

    public static bool AreReferencesEqual<T>(T i1, T i2) where T : class
    {
        return i1 == i2;
    }

Driver method:

    static void Main(string[] args)
    {
        string name = "Joe";
        string one = "one" + name;
        string two = "one" + name;
        // test one (uses string operator== overload, and returns true)
        Console.WriteLine(one == two);

        // test two (according to Jon, when the compiler compiles the generic method,
        // it has no idea what overloads will be provided, and therefore treats
        // the == comparison with respect to the more general 'object' type.
        // Therefore this method should return false because, of course, the value
        // of the references 'one' and 'two' are not the same.
        Console.WriteLine(ReferenceEquality.AreReferencesEqual(one, two));
    }

In consistency with Jon's explanation, the output of the driver file when I run it is "True", "False". Now, I thought I understood this completely, but I was surprised when I changed the driver file to this:

    static void Main(string[] args)
    {
        string one = "one";
        string two = "one";
        Console.WriteLine(one == two);
        Console.WriteLine(ReferenceEquality.AreReferencesEqual(one, two));
    }

and saw "True", "True" on the output. What is the reasoning behind this? Is the generic method now using the string operator== overload, or are the references indeed equal as a result of some subtle compiler technique I am unaware of? Or have I completely missed the boat and misinterpreted Jon's explanation?

Thanks for taking the time to read and respond.

They are reference-equivalent because the compiler is using the same underlying string because the constants match. Strings (behind the scenes) are immutable in C# - when you add strings together, a new string instance is generated - that never happens in your second code set, so they are, in fact, both referencing the same chunk of bytes in RAM.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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