【发布时间】:2013-07-16 13:10:21
【问题描述】:
我不完全确定如何使这个问题可读/易懂,但请听我说完,我希望当我们结束时你能理解我的问题(至少,它很容易重现)。
我尝试在 UnitTests 中调用用于验证结果的方法。它具有以下签名:
void AssertPropertyValues<TEnumerable, TElement, TProperty>(
TEnumerable enumerable,
Func<TElement, TProperty> propertyPointer,
params TProperty[] expectedValues)
where TEnumerable : System.Collections.Generic.IList<TElement>
这意味着,它需要以下输入
- 任何可枚举的对象,并且包含与 2) 的输入相同类型的对象。
- 一个 Func(通常封装 lambda 表达式),它接受与 1) 的“内容”相同类型的对象,并返回与 3) 中提供的数组内容的类型相同类型的对象。
- 与 2) 中 Func 的输出具有相同类型的对象数组。
因此,此方法的实际执行可能如下所示:
AssertPropertyValues(
item.ItemGroups,
itemGroup => itemGroup.Name,
"Name1", "Name2", "Name3");
至少,我希望它看起来像这样,但我遇到了众所周知的编译器错误:“无法从用法中推断出方法 'X' 的类型参数。”,这就是我不明白。据我所知,它应该包含所需的所有信息,或者它可能是“协方差和逆变”问题的另一个版本?
所以现在我不得不这样做:
AssertPropertyValues(
item.ItemGroups,
(ItemGroup itemGroup) => itemGroup.Name,
"Name1", "Name2", "Name3");
谁能指出为什么编译器无法推断出这种情况?
【问题讨论】:
-
您是否尝试过使用
IEnumerable<TElement>或类似的东西来代替TEnumerable?基本上propertyPointer-parameter 应该与谓词相同,例如Enumerable.Select-extension 方法中的谓词(因此整个构造工作相似)...item.ItemGroups具有哪种类型(任何不匹配,这使得显式签名成为强制性?)?否则我不明白你面临的问题...... -
我已经修复了您的代码示例的格式,以便它们合理并重命名您的问题;这与 lambda 无关。
-
@AndreasNiedermair 我的问题源于我最初在多个地方都有此约束,并且在某些地方将它们用作返回类型,因此不能仅使用接口“凑合”。尝试 EricLippert 的解决方案时不再是这种情况了。
-
@EricLippert:第二个参数是一个 lambda 表达式,这不是让我开始遇到问题的原因吗?如果我使用委托,编译器将拥有所需的所有信息。