C#为什么这种类型的推断方法调用模糊不清?

Mic*_*ahn 11 c#

以下函数对尝试复制C#6.0中可用的空条件运算符:

public static TResult Bind<T, TResult>(this T obj, Func<T, TResult> func)
    where T : class
{
    return obj == null ? default(TResult) : func(obj);
}

public static TResult Bind<T, TResult>(this Nullable<T> obj, Func<T, TResult> func)
    where T : struct
{
    return obj.HasValue ? func(obj.Value) : default(TResult);
}
Run Code Online (Sandbox Code Playgroud)

第一个函数被约束到类,并且String s允许我写一些类似的东西:

var x = s.Bind(a => a.Substring(1));
Run Code Online (Sandbox Code Playgroud)

第二个功能是我遇到麻烦的地方.例如,给int? number我一个我想写的:

var y = number.Bind(a => a + 1);
Run Code Online (Sandbox Code Playgroud)

但是,这给了我以下错误:

以下方法或属性之间的调用是不明确的:'​​BindingExtensions.Bind <T,TResult>(T,Func <T,TResult>)'和'BindingExtensions.Bind <T,TResult>(T?,Func <T,TResult >)"

我猜这与匿名函数的类型推断和方法重载决策之间的相互作用有关.如果我指定a的类型,int那么编译就好了.

var y = number.Bind((int a) => a + 1);
Run Code Online (Sandbox Code Playgroud)

然而,这显然不太理想.任何人都可以告诉我为什么编译器认为上面的绑定调用是模糊的和/或提供一种方法来解决这个问题?我知道我可以简单地命名这两个函数,但那有什么乐趣?

eri*_*sco 2

重载函数无法通过类型约束来消除歧义(请参阅“通用约束,where T : struct 和 where T : class ”)。任何可空类型 N 都满足N : TN : Nullable<T>,分别是前一个和后一个Bind定义所要求的。我猜那number是类型Nullable<int>或类似的。

var x = s.Bind(a => a.Substring(1));
Run Code Online (Sandbox Code Playgroud)

这是明确的,因为sis 类型string并且对于所有Tnot 类型string : Nullable<T>,因此只有第一个重载是可接受的。

var y = number.Bind(a => a + 1);
Run Code Online (Sandbox Code Playgroud)

这是不明确的,因为 的类型a => a + 1可以被推断为Func<int?,int?>Func<int,int>。如果推断为Func<int?,int?>第一过载,则适用,并且如果推断为Func<int,int>第二过载,则适用。

var y = number.Bind((int a) => a + 1);
Run Code Online (Sandbox Code Playgroud)

例如,如果number是 类型,则这是明确的。Nullable<int>对于所有TnotT : Nullable<int>和 的第一个重载T : int,因此它不适用。对于第二个重载,您只需要T : int它很容易满足T = int

  • `Nullable&lt;T&gt;` 本身就是一个结构体,不是吗?[链接](https://msdn.microsoft.com/en-us/library/b3h38hb0(v=vs.110).aspx)那么“int?”如何满足类约束呢? (3认同)