【发布时间】:2012-06-27 22:11:51
【问题描述】:
所以,IEnumerable 的一个相当常见的扩展方法,Run:
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重载在对方法组无效的情况下怎么会导致歧义?
【问题讨论】:
-
db.InvoiceItems.Add的签名是什么? -
简短回答:
x => x.ToString()这个 lambda 应该简单地调用 ToString 还是调用 ToString 并返回其结果?换句话说,这个 lambda 应该作为一个函数还是一个动作来处理?编译器无法为您做出此决定,因此出现错误。 -
@Polity 但是这里没有 lambda。并且从方法组转换为委托永远不会将返回某物的方法更改为
void-returning 委托。 -
@svick - Lambda 是 .NET 生态系统中的奇怪公民。只有它们取决于声明的类型(因此您不允许使用 var)。分配给操作的 lambda 根本不会返回。当重载决议必须在一个动作和一个函数之间进行选择时,它真的变成了一个丑陋的选择。现在我假设*编译器提前检测到这些问题并因此产生错误。
-
@Polity 我相信 Eric Lippert 对问题 roken 的回答很好地描述了这个问题。