c# - 泛型方法重载与可空类型不明确

标签 c# generics .net-4.0 ambiguous overload-resolution

假设我有两个通用的重载方法:

public string Do<T>(T maybeValue, Func<T, string> func)
  where T : class
{
  if(maybeValue == null) return null;
  return func(maybeValue);
}

public string Do<T>(T? maybeValue, Func<T, string> func)
  where T : struct
{
  if(!maybeValue.HasValue) return null;
  return func(maybeValue.Value);
}

现在,使用可空类型的变量调用方法,C# 拒绝编译并表示调用在两个重载之间不明确:

int? maybeX = 3;
Do(maybeX, x => x.ToString());

The call is ambiguous between the following methods or properties: 'Program.Do<int?>(int?, System.Func<int?,string>)' and 'Program.Do<int>(int?, System.Func<int,string>)'

简单的修复是在调用方法时包含泛型参数,或者指定 lambda 参数的类型:

Do<int>(maybeX, x => x.ToString());
Do(maybeX, (int x) => x.ToString());

有趣的是,选择int?作为调用期间的通用类型将不会编译

The type must be a reference type in order to use it as parameter 'T' in the generic type or method".

怎么会?显然,两个重载中只有一个可以与 int? 类型的值一起使用。 ,但编译器说调用不明确。我可以进一步限制方法以帮助编译器决定调用哪个方法,而无需调用代码明确指定类型吗?

最佳答案

where T : class约束不是方法签名的一部分。该检查稍后在方法重载选择过程中进行。
这就是为什么它被认为是模棱两可的。在检查任何约束之前,这两种方法都是匹配的。
如果你明确地说 Do<int?>只有第一个方法是匹配的,但随后约束“启动”并确定它无效,因为 int?不是引用类型。

如果将其更改为:将选择第二种方法:

public static string Do<T>(T? maybeValue, Func<T?, string> func)
    where T : struct

关于c# - 泛型方法重载与可空类型不明确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31803273/

相关文章:

c# - 在抽象通用测试类中定义单元测试

c# - 如何在 C# 3.5 中对泛型方法施加接口(interface)约束?

.net-4.0 - 我可以使用 useLegacyV2RuntimeActivationPolicy 运行 scriptcs 吗?

c# - 按具有混合值的两个条件对值进行分组

javascript - 如何使用 Selenium 滚动到元素内部的底部?

swift - 为什么我不能将 Protocol.Type 传递给通用 T.Type 参数?

c# - 创建代表一系列连续任务的任务

.net - WCF内部队列监控(为了避免向服务发送太多请求)

c# - 界面设计?我可以迭代地做吗?我应该如何处理界面的更改?

javascript - 使用 Javascript 在 EditorFor MVC 中获得焦点