这个问题在这里已有答案:
因此,IEnumerable的一个相当常见的扩展方法,运行:
public static IEnumerable<T> Run<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (var item in source)
{
action(item);
yield return item;
}
}
当我尝试使用它时,例如,DbSet.Add:
invoice.Items.Run(db.InvoiceItems.Add);
// NB: Add method signature is
// public T Add(T item) { ... }
...编译器抱怨它有错误的返回类型,因为它期望一个void方法 . 因此,为Run添加一个重载,它接受一个Func而不是Action:
public static IEnumerable<T> Run<T>(this IEnumerable<T> source, Func<T, T> action)
{
return source.Select(action).ToList().AsEnumerable();
}
现在编译器抱怨说“以下方法之间的调用是模糊的......”
所以我的问题是,当Run方法的Action重载对方法组无效时,怎么会导致歧义?
4 回答
这已经由Eric和Jon在this question的答案中解释过了 . 长话短说 - 这就是C#编译器的工作原理;确切地说,在处理方法组转换时,决定将转换为什么委托使用重载分辨率, does not take return types in account :
在您的示例中,编译器将
Action<T>
和Func<T, T>
视为Add
的最佳匹配 . 这增加了两种可能的选择,因为它需要一个 - 发出适当的错误 .尝试以正确的方式过载:
我无法回答为什么,但为了解决你可以明确表达你的功能的歧义:
或者使用lambda
我不知道为什么它无法自动解决它,但这里有两个解决方法:
为什么你还需要这些方法?出了什么问题:
这个的可读性要好得多 . 除非你有充分的理由需要
Run
方法,我已经看到了,所以没有这样的理由,至少对于Action<T>
重载 .