泛型类型参数和Nullable方法重载

Hen*_*Ten 9 .net c# generics types 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
Run Code Online (Sandbox Code Playgroud)

请注意TInput约束,一个是类,另一个是struct.然后我用它们:

string s;
int? i;

// ...

s.With(o => "");
i.With(o => ""); // Ambiguos method
Run Code Online (Sandbox Code Playgroud)

它会导致Ambiguos错误.但我还有另一对:

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
Run Code Online (Sandbox Code Playgroud)

这个编译成功

string s;
int? i;

// ...

s.Return(o => 1, 0);
i.Return(o => i + 1, 0);
Run Code Online (Sandbox Code Playgroud)

我没有找到为什么会发生这种情况的线索.第一个看起来好,但编译错误.第二个('Return')如果是第一个,则应该是错误,但是成功编译.我错过了什么?

Jon*_*eet 10

选择过载时不考虑通用方法中的约束- 在选择过载检查它们.

参数类型内的约束选中为选择过载的一部分.这有点令人困惑,但最终才有意义.

我有一篇关于此的博文可能有助于进一步理解它.

另外请注意,您的第二个示例具有有助于类型推断的附加参数,这是两者之间的区别.TResult被推断为int,这防止是有效的所述第一过载-有没有从转换(int? x) => x + 1Func<int?, int>而有从一个转换(int x) => x + 1Func<int, int>.