你好 我有使用泛型和可空的代码:
// 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
请注意TInput约束,一个是类,另一个是struct。然后我用它们:
string s;
int? i;
// ...
s.With(o => "");
i.With(o => ""); // Ambiguos method
导致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
这个编译成功
string s;
int? i;
// ...
s.Return(o => 1, 0);
i.Return(o => i + 1, 0);
我没有找到为什么会发生这种情况的线索。第一个看起来好,但编译错误。第二个('Return')如果是第一个,则应该是错误,但是成功编译。我错过了什么吗?
答案 0 :(得分:10)
在选择过载时,不考虑泛型方法中的约束 - 在选择了重载后,它们会被检查。
作为选择过载的一部分,参数类型中的约束被检查。这有点令人困惑,但最终才有意义。
我有一个blog post,这有助于进一步理解它。
另外请注意,您的第二个示例具有附加参数,该参数有助于类型推断,这是两者之间的区别。 TResult
被推断为int
,可防止第一次重载生效 - 从(int? x) => x + 1
到Func<int?, int>
没有转换,而是 a从(int x) => x + 1
转换为Func<int, int>
。