无法使用表达式初始化 LambdaExpression

发布于 2024-11-29 11:04:44 字数 849 浏览 0 评论 0 原文

问题类似于 John K 的 one by John K,但更具体,并且接受的答案并不不适合我的需要。

这编译得很好:

Expression<Func<object, object>> specificExpression = (object o) => new object();
Expression generalExpression = specificExpression;

而这个则不然:

Expression generalExpression = (object o) => new object();

报告编译错误:

无法将 lambda 表达式转换为类型“System.Linq.Expressions.Expression”,因为它不是委托类型

Expression> 派生自Expression

现在我有一个框架,其中的方法接受各种表达式,即类型Expression。在每个方法调用上被迫将 lambda 显式转换为相应的 Expression> 是令人沮丧的。

在这种情况下,有什么好的理由可以解释为什么这种基本的 OOP 行为会被破坏吗?

Question similar to one by John K, but more specific and the accepted answer doesn't suit my needs.

This compiles fine:

Expression<Func<object, object>> specificExpression = (object o) => new object();
Expression generalExpression = specificExpression;

And this one doesn't:

Expression generalExpression = (object o) => new object();

Reported compile error:

Cannot convert lambda expression to type 'System.Linq.Expressions.Expression' because it is not a delegate type

Expression<Func<T1,T2>> derives from Expression.

Now I have a framework with methods accepting all sorts of expressions, i.e. type Expression. Being forced to explicitly cast lambdas to the corresponding Expression<Func<T1,T2>> on each method call is frustrating.

Any good reasons why this basic OOP behavior is broken in this case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

何以笙箫默 2024-12-06 11:04:44

转换不起作用,因为编译器无法推断您正在尝试创建哪种特定表达式类型。如果你这样做了怎么办?

Expression generalExpression = (object o) => "foo";

这应该是 Expression> 吗? Expression>Expression> 怎么样?这些类型都是表达式树的有效最终类型,并且编译器不会假装知道您要做什么。

您需要通过特定类型进行转换,以通知编译器您想要生成哪种类型的表达式:

Expression generalExpression = (Expression<Func<object, object>>)
    (object o) => new object();

如果您尝试这样做,您会看到类似的编译器错误:

Delegate generalDelegate = delegate() { };

Is that an Action, or a ThreadStart,或其他类型的无参数无效返回委托?

The conversion doesn't work because the compiler cannot infer which specific expression type you are trying to create. What if you did this?

Expression generalExpression = (object o) => "foo";

Should this be an Expression<Func<object, string>>? What about Expression<Func<object, object>> or Expression<Func<object, IComparable>>? These types would all be a valid final type for the expression tree, and the compiler doesn't pretend to know what you are trying to do.

You need to cast through the specific type to inform the compiler which type of expression you want to produce:

Expression generalExpression = (Expression<Func<object, object>>)
    (object o) => new object();

You would see a similar compiler error if you tried this:

Delegate generalDelegate = delegate() { };

Is that an Action, or a ThreadStart, or some other kind of no-argument void-returning delegate?

爱殇璃 2024-12-06 11:04:44

当您编写

Expression> 时,具体表达式 = (对象 o) => new object();

这实际上是 C# 编译器为我们提供的一种易于编写的方法。

这个表达式实际上会被编译成这样的:

Expression.Lambda<Func<object, object>> specificExpression = Expression.Lambda<Func<object,object>> ( ... )

正如你所看到的,Expression> 不是委托类型,即使第一个表达式可能会导致我们出错并且让我们相信情况确实如此。

“Expression”不是委托类型,因此您不能直接将其分配为委托对象,因为编译器不提供编写的便利性(与 Expression 类一样)。

很抱歉这么说,但你必须走这条令人沮丧的路。

瑞安娜

When you write

Expression<Func<object, object>> specificExpression = (object o) => new object();

It is actually an ease of writing that the C# compiler offers to us.

This expression will actually be compiled to something like this :

Expression.Lambda<Func<object, object>> specificExpression = Expression.Lambda<Func<object,object>> ( ... )

and as you can see, Expression<Func<object,object>> is not a delegate type even if the first expession could induce us in error and let us believe that this is the case.

"Expression" is not of delegate type, so you can't assign it directly a delegate object because the compiler doesn't offer the ease of writing (as it does for Expression<T> classes).

Sorry to say that but you have to go the frustrating way.

Riana

冷月断魂刀 2024-12-06 11:04:44

C# 编译器将表达式计算为最简单的复杂形式,例如:

 var x = (object o) => new object();

x 应该是 Func,而不是 Expression>。在这种情况下,编译器确定该值是委托,并且由于 Expression 无法接受委托(仅 Expression>> / Expression 类型即可),则抛出编译器错误。

另外,请参阅@Riana的答案,因为表达式形式实际上是由编译器重写的。

The C# compiler evaluates the expression to the least complex form, for example:

 var x = (object o) => new object();

x should be a Func<object, object>, not an Expression<Func<object, object>>. In this case, the compiler is determining the value is a delegate, and since Expression cannot take a delegate (only the Expression<Func<>> / Expression<Action> types can), the compiler error is thrown.

Also, see @Riana's answer, because the expression form is actuall rewritten by the compiler.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文