gpt4 book ai didi

c# - 对传递 Expression 与 Func 参数感到困惑

转载 作者:可可西里 更新时间:2023-11-01 03:00:24 25 4
gpt4 key购买 nike

我在理解表达式和函数的工作方式之间的区别时遇到了一些困难。当有人更改方法签名时出现此问题:

public static List<Thing> ThingList(Func<Thing, bool> aWhere)

public static List<Thing> ThingList(Expression<Func<Thing, bool>> aWhere)

这破坏了我的调用代码。旧的调用代码(有效)如下所示:

        ...
object y = new object();
Func<Thing, bool> whereFunc = (p) => p == y;
things = ThingManager.ThingList(whereFunc);

新代码(不起作用)如下所示:

        ...
object x = new object();
Expression<Func<Thing, bool>> whereExpr = (p) => p == x;
things = ThingManager.ThingList(whereExpr);

ThingList(...) 中使用表达式的行失败了:

        var query = (from t in context.Things.Where(aWhere)
...

运行时错误:

Unable to create a constant value of type 'System.Object'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.

这个例子是人为设计的,但我猜它与局部对象变量 x 没有被正确地“复制”到表达式中有关。

有人可以解释一般情况下如何处理这种情况,以及为什么 Func 有效而 Expression 无效?

最佳答案

更改的原因几乎可以肯定是将谓词的评估“推送”到支持您的 context 的底层存储中。 .而不是带上所有 Things存入内存,然后使用 Func<Thing,bool>为了决定保留哪些,更改后的 API 的作者决定使用 IQueryable , 并且需要一个 Expression<Func<Thing,bool>>为此。

您对错误的起源是正确的:与内存谓词不同,IQueryable不能使用它不知道的对象,例如object 的任意实例.

您需要做的是更改表达式以避免引用目标数据存储不支持的数据类型的对象(我假设表达式最终会进入 Entity Framework 或 Linq2Sql 上下文)。例如,而不是说

object x = new object();
Expression<Func<Thing, bool>> whereExpr = (p) => p == x;
things = ThingManager.ThingList(whereExpr);

你应该说

Thing x = new Thing {id = 123};
Expression<Func<Thing, bool>> whereExpr = (p) => p.id == x.id;
things = ThingManager.ThingList(whereExpr);

(您的后备存储几乎肯定能理解整数)

关于c# - 对传递 Expression 与 Func 参数感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8728357/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com