Pellared
Pellared

Reputation: 1292

C# overloading with generic constraints

Why those two methods cannot have the same name? Is it because C# compiler does not take the generic type constraints into consideration for overloading? Could it be done in future releases of C#?

public static TValue GetValueOrNull<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
            where TValue : class
{
    TValue value;
    if (dictionary.TryGetValue(key, out value))
        return value;
    return null;
}

public static TValue? GetValueOrNull<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
        where TValue : struct
{
    TValue value;
    if (dictionary.TryGetValue(key, out value))
        return value;
    return null;
}

Upvotes: 7

Views: 2282

Answers (2)

shingo
shingo

Reputation: 27011

Could it be done in future releases of C#?

With the emergence of nullable reference types, this has become possible today, but the type parameters must appear in the parameter list.

public static bool GetValueOrNull<TKey, TValue>(
    this IDictionary<TKey, TValue> dictionary,
    TKey key, out TValue? value) where TValue : class
{
    return dictionary.TryGetValue(key, out value);
}

public static bool GetValueOrNull<TKey, TValue>(
    this IDictionary<TKey, TValue> dictionary,
    TKey key, out TValue? value) where TValue : struct
{
    if(dictionary.TryGetValue(key, out TValue v))
    {
        value = v;
        return true;
    }
    value = null;
    return false;
}

Upvotes: 0

Damien_The_Unbeliever
Damien_The_Unbeliever

Reputation: 239656

Absolutely correct. See section 3.6 of the C# Language Spec (version 5):

The signature of a method consists of the name of the method, the number of type parameters and the type and kind (value, reference, or output) of each of its formal parameters, considered in the order left to right. For these purposes, any type parameter of the method that occurs in the type of a formal parameter is identified not by its name, but by its ordinal position in the type argument list of the method. The signature of a method specifically does not include the return type, the params modifier that may be specified for the right-most parameter, nor the optional type parameter constraints.

(My emphasis)

So the signature of both methods is effectively:

GetValueOrNull<T1,T2>(IDictionary<T1,T2>,T1)

And:

Overloading of methods permits a class, struct, or interface to declare multiple methods with the same name, provided their signatures are unique within that class, struct, or interface.


Could it be done in future releases of C#?

I doubt it, unless or until type inference becomes an easier problem to solve. Type inference can already take large amounts of time because the compiler usually has to perform a brute-force approach. It having to also consider overload resolution at the same time may be prohibitively expensive given current machines.

Upvotes: 10

Related Questions