【发布时间】:2018-04-06 12:58:42
【问题描述】:
以下 3 个方法是我使用的库 FakeItEasy 的一部分:
public static T Matches<T>(this IArgumentConstraintManager<T> scope, Func<T, bool> predicate, string description);
public static T Matches<T>(this IArgumentConstraintManager<T> manager, Func<T, bool> predicate, string descriptionFormat, params object[] args);
public static T Matches<T>(this IArgumentConstraintManager<T> scope, Expression<Func<T, bool>> predicate);
我在使用 Visual Studio 2017 时遇到以下问题。
我想提供一个谓词作为Func<T,bool> 而不是Expression<Func<T, bool>>。
原因是我的函数比较了一个类的动态属性,看起来像这样:
A.CallTo(() => A<Class>.That.Matches(obj => obj.DynamicProperty == "text")).MustHaveHappened();
DynamicProperty 标有 dynamic 关键字,我收到编译时错误提示
表达式树可能不包含动态操作
https://i.imgur.com/ujetxPh.png
好的我明白了。表达式中不支持它。
我想选择一个使用Func<T, bool>的重载。
如果有两种方法只是谓词类型(表达式和函数)不同,我该如何选择一个?
正如您在上面的方法定义中看到的,Func<T,bool> 重载有一个额外的string description 参数。我希望这足以让编译器选择适当的重载。
所以我把我的电话改成这样了:
A.CallTo(() => A<Class>.That.Matches(obj => obj.DynamicProperty == "text", "testing")).MustHaveHappened();
仍然出现相同的编译器时间错误,但是当我现在将鼠标悬停在 Visual Studio 中的方法上时,工具提示显示选择的方法是 Func<T,bool> 之一。
那么为什么我仍然无法编译它并显示有关表达式树的错误信息?我不想使用任何表达式树!
所以我只有将谓词放在单独的方法中才能编译它
public bool Test(Class obj){
return obj.DynamicProperty == "text";
}
并将我的支票更改为
A.CallTo(() => A<Class>.That.Matches(Test, "testing")).MustHaveHappened();
这似乎可以解决问题。
但我仍然希望编译器将我使用 lamda 语法编写的函数视为 Func<T,bool> 而不是 Expression<Func<T,bool>>。
这是 VS 或编译器中的错误还是我遗漏了什么?
编辑 - 重现它的步骤/设置
创建一个空白的控制台项目替换packages.config和Program.cs:
https://gist.github.com/michaelbudnik/33f3dd39df038ba1d02f01dc9659002b
【问题讨论】:
-
通过定义已知类型为
Func<T, bool>的方法,如果您在调用之前在变量中定义函数,例如var test = new func<Class , bool>((class)=> {class.DynamicProperty == "text";});然后调用传递函数的匹配项 -
但如果不这样做,则 lambda 可能同时是
Func<T, bool>和Expression<Func<T, bool>>。那么为什么编译器不警告您这种歧义并选择带有表达式参数的方法呢?即使添加了一个应该是鉴别器的附加参数,它仍然会抱怨表达式中不支持的动态属性 -
如果有两个方法,一个参数是
Expression,另一个是Func,编译器会返回歧义错误。 -
这与 Fluent 断言有什么关系。这篇文章谈到了 FakeItEasy。
-
@DennisDomen 是的,对不起。编辑标签
标签: c# .net fakeiteasy