【问题标题】:Generic method overload ambiguous with nullable types泛型方法重载与可空类型不明确
【发布时间】:2015-08-04 07:34:39
【问题描述】:

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

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);
}

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

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

以下方法或属性之间的调用不明确: 'Program.Do&lt;int?&gt;(int?, System.Func&lt;int?,string&gt;)' 和 'Program.Do&lt;int&gt;(int?, System.Func&lt;int,string&gt;)'

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

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

有趣的是,在调用期间选择int? 作为泛型类型将无法编译

类型必须是引用类型才能在泛型类型或方法中用作参数“T”。

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-26
      • 2011-07-18
      • 2012-06-05
      • 1970-01-01
      • 2013-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多