c#为什么这个类型推断方法调用有歧义
本文关键字:方法 调用 歧义 为什么 类型 | 更新日期: 2023-09-27 18:04:51
下面两个函数试图复制c# 6.0中可用的null条件运算符:
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);
}
第一个函数被限制为类,对于String s
,我可以这样写:
var x = s.Bind(a => a.Substring(1));
第二个函数是我遇到麻烦的地方。例如,给定一个int? number
,我想写:
var y = number.Bind(a => a + 1);
然而,这给了我以下错误:
调用在以下方法或属性之间是不明确的:'BindingExtensions.Bind<T,>(T, Func<T,>)'和'BindingExtensions.Bind<T,>(T?, Func<T,>)'
我猜这与匿名函数的类型推断和方法重载解析之间的相互作用有关。如果我指定a的类型为int
,那么它可以正常编译。
var y = number.Bind((int a) => a + 1);
然而,这显然是不理想的。谁能告诉我为什么编译器认为上面的调用绑定是模棱两可的和/或提供一种方法来解决这个问题?我知道我可以简单地用不同的名字命名这两个函数,但这有什么好玩的?
不能通过类型约束消除重载函数的歧义(参见"泛型约束,其中T: struct和T: class")。任何可空类型N都满足N : T
和N : Nullable<T>
,分别满足Bind
定义的要求。我猜number
的类型是Nullable<int>
或类似的。
var x = s.Bind(a => a.Substring(1));
这是明确的,因为s
是string
类型的,并且对于所有T
而不是string : Nullable<T>
,所以只有第一个重载是可接受的。
var y = number.Bind(a => a + 1);
这是有歧义的,因为a => a + 1
的类型可以被推断为Func<int?,int?>
或Func<int,int>
。如果推断为Func<int?,int?>
,第一个重载应用,如果推断为Func<int,int>
,第二个重载应用。
var y = number.Bind((int a) => a + 1);
例如,如果number
是Nullable<int>
类型,则这是明确的。对于所有T
不是T : Nullable<int>
和T : int
的第一个重载,所以它不适用。对于第二次重载,您只需要T : int
, T = int
很容易满足。
试试这个:
public static TResult Bind<T, TResult>(this T? obj, Func<T?, TResult> func)
where T : struct
{
return obj.HasValue ? func(obj.Value) : default(TResult);
}