简体   繁体   中英

Generic type parameter and Nullable method overload

Hi
I have this code using generic and nullable:

// The first one is for class
public static TResult With<TInput, TResult>(this TInput o, 
          Func<TInput, TResult> evaluator)
    where TResult : class
    where TInput : class

// The second one is for struct (Nullable)
public static TResult With<TInput, TResult>(this Nullable<TInput> o, 
          Func<TInput, TResult> evaluator)
    where TResult : class
    where TInput : struct

Please note the TInput constraint, one is class, the other one is struct. Then I use them in:

string s;
int? i;

// ...

s.With(o => "");
i.With(o => ""); // Ambiguos method

It cause an Ambiguos error. But I also have the another pair:

public static TResult Return<TInput, TResult>(this TInput o,
          Func<TInput, TResult> evaluator, TResult failureValue)
    where TInput : class

public static TResult Return<TInput, TResult>(this Nullable<TInput> o,
          Func<TInput, TResult> evaluator, TResult failureValue)
    where TInput : struct

This one compiles successfully

string s;
int? i;

// ...

s.Return(o => 1, 0);
i.Return(o => i + 1, 0);

I got no clues why this happen. The first one seems Ok, but compiles error. The second one ('Return') should be error if the first one is, but compiles successfully. Did I miss something?

Constraints within the generic method are not considered while choosing an overload - they're checked after the overload has been chosen.

Constraints within the types of the parameters are checked as part of choosing an overload. It's a bit confusing, but it makes sense eventually.

I have ablog post on this which may help to understand it further.

Additionally note that your second example has the additional argument which contributes to type inference, which is what makes the difference between the two. TResult is inferred to be int , which prevents the first overload from being valid - there's no conversion from (int? x) => x + 1 to Func<int?, int> whereas there is a conversion from (int x) => x + 1 to Func<int, int> .

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