开发者

Why two generic types cannot be compared with '=='?

开发者 https://www.devze.com 2023-01-11 00:19 出处:网络
Here is my simple code: T a; T b; if (a == b) // sth. else // sth. e开发者_开发技巧lse When I try to compile, I get an error saying the == operator is invalid for generic types. So I have to use t

Here is my simple code:

T a;
T b;

if (a == b)
// sth.
else
// sth. e开发者_开发技巧lse

When I try to compile, I get an error saying the == operator is invalid for generic types. So I have to use the object.Equals() method.

Doesn't the == operator actually call the Equals method of object? Why can I use the Equals method of two generic types but not the == operator?


operator == must be overloaded in structs in order to be used, hence a completely unconstrained type parameters cannot use it. You can constrain the function to class to allow default reference comparison:

    public void Foo<T>() where T : class {
        T a = default(T);
        T b = a;

        if(a == b)
            System.Diagnostics.Debug.WriteLine("");
        else
            System.Diagnostics.Debug.WriteLine("");
    }

The above code works because by default, reference types can be used with operator ==:

For reference types other than string, == returns true if its two operands refer to the same object.

This is why if (new object() == new object()) {} compiles, even though System.Object doesn't overload operator ==.


The == operator is not defined all possible values of T [thanks Daniel] (or on any constraints you may have placed on T, I assume), so you can't use it. You can only call operators, methods, properties on T that can be called on ALL possible types represented by T.

operator == calls 'Equals' in many cases, but that doesn't mean they are the same thing.


The == token is used to represent two different operators in C#. The first of them is applicable only if the types of the operands fit a particular defined overload of the "equality-check" operator. The second test reference equality and is applicable only if one operand is null, one operand is a class type and the other an interface that instances of that type could implement, both are interfaces, both are the same class types, or both are class types and one is a supertype of the other. The first form will not be usable on a generic unless the generic is constrained to a type for which an equality-check overload is defined; the second form is limited to reference types which are known to satisfy a particular one of the indicated conditions. Note that in some cases, the second operator may be used where the first would be intended, e.g. bool IsSame<T>(T p1, T p2) where T:class { return p1==p2; } will compare two variables of type String by using a reference comparison, even though an overload of == is defined for String. This occurs because T isn't well-enough known to apply a String overload of ==, but both operands of == are known to be the same reference type.

It may be worth noting that some other languages use different tokens for the two operations C# performs using ==. VB.NET, for example, uses = for equality comparison and Is for reference equality.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号