C# 泛型类型参数和可为null的方法重载

C# 泛型类型参数和可为null的方法重载,c#,.net,generics,types,nullable,C#,.net,Generics,Types,Nullable,嗨 我使用泛型和可空的代码: // 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 (Nulla


我使用泛型和可空的代码:

// 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
这会导致含糊不清的错误。但我还有另一双:

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

我不知道为什么会这样。第一个看起来不错,但编译错误。如果第一个是,但编译成功,则第二个('Return')应该是error。我遗漏了什么吗?

选择重载时不考虑泛型方法中的约束-在选择重载后会检查这些约束

作为选择重载的一部分,将检查参数类型中的约束。这有点令人困惑,但最终还是有道理的

我对这一点有一些看法,这可能有助于进一步了解它


另外请注意,您的第二个示例有一个附加的参数,它有助于类型推断,这就是两者之间的区别
TResult
被推断为
int
,这会阻止第一个重载有效-没有从
(int?x)=>x+1
Func
的转换,而有从
(int x)=>x+1
Func

的转换,只是作为样式注释,我会避免对lambda参数使用与scope中已经存在的变量相同的名称。啊,对了,这实际上会导致编译错误。我只是匆忙地粘贴和编辑了代码。我现在很困惑,我正在努力理解你的最后一段。两个Func委托根本不使用nullable(int?)。只有第一个参数是。@Hendry:每种情况下的第一个重载都将处理
TInput=int?
,因为您在
int?
上调用它。因此,
evaluator
参数类型将是
Func
。哦,我明白了,这就是为什么基于lambda函数的重载解析在第一次“返回”时失败,并流到第二次。非常感谢。请参阅更新链接。
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);