简体   繁体   中英

Operator overloading with generic function parameters

I have a problem with operator resolution on generic methods.

From my understanding of section 7.3.4 of the spec within the function EqualOperatorGeneric (sample code below) the correct overload of the == operator on the type A should be found, but instead it seems to get the candidate for (object, object).

Am I doing something very obvious wrong? Is there a method to get the expected behaviour and if not can I turn the given case into a compile time or runtime error?

public class A
{
    public A(int num)
    {
        this.Value = num;
    }

    public int Value { get; private set; }

    public override bool Equals(object obj)
    {
        var other = obj as A;
        if (Object.ReferenceEquals(other, null))
            return false;

        return Object.Equals(this.Value, other.Value);
    }

    public override int GetHashCode()
    {
        return this.Value.GetHashCode();
    }

    public static bool operator ==(A l, A r)
    {
        if (Object.ReferenceEquals(l, null))
        {
            return !Object.ReferenceEquals(r, null);
        }

        return l.Equals(r);
    }

    public static bool operator !=(A l, A r)
    {
        return !(l == r);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(EqualOperatorGeneric(new A(1), new A(1)));
    }

    public static bool EqualOperatorGeneric<L, R>(L l, R r)
        where L : class
        where R : class
    {
        return l == r;
    }
}

Output:

False

When EqualOperatorGeneric is compiled the == operator needs to be bound statically, when the method is compiled, to a single implementation. It is not bound separately for each separate usage of the generic method.

This is what differentiates generics from, say, C++ templates. The generic method is compiled once and then applied to every usage with every set of type arguments, whereas templates are compiled separately for each set of generic arguments.

After scrounging the spec I realized you can use the dynamic keyword to defer binding of the operator from compile time to runtime. This fixes the issues I have been having:

public static bool EqualOperatorGeneric<L, R>(L l, R r)
{
    dynamic dl = l, dr = r;
    return dl == dr;
}

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