【问题标题】:C# Compiled Expression as ConsoleApplication ReadLine not pausingC# 编译表达式作为 ConsoleApplication ReadLine 没有暂停
【发布时间】:2018-01-05 18:57:02
【问题描述】:

我正在尝试将 linq 表达式编译为 .exe 文件到控制台应用程序。

以下代码工作正常并暂停:

LambdaExpression expr1 = Expression.Lambda<Action<string[]>>(
Expression.Call(typeof(Console).GetMethod("ReadLine")),
Expression.Parameter(typeof(string[])));

但是,当像这样在另一个 lambda 中调用 lambda 时:

var parameter = Expression.Parameter(typeof(string[]));
LambdaExpression expr1 = Expression.Lambda<Action<string[]>>(
    Expression.Lambda<Action<string[]>>(
        Expression.Call(typeof(Console).GetMethod("ReadLine")),
        parameter), parameter);

它只是关闭控制台而不暂停。

通过 AssemblyBuilder 创建一个 Assembly 和一个由 expr1.CompileToMethod(methodBuilder) 填充的 MethodBuilder 来编译表达式;

嵌套的 lambdas 不起作用还是我必须以不同的方式使用它?

编辑:正如@Servy 指出的那样,Expression.Lambda 只会创建但不会执行 lambda。

可以使用以下答案在表达式中执行 lambda:How to call a lambda using LINQ expression trees in C# / .NET

Expression.Invoke(Expression.Constant(innerLambda), 参数);

【问题讨论】:

  • 调试时需要在任何控制台应用程序的末尾放置一个 Console.ReadKey() 或类似命令。否则它会在您有时间阅读输出之前关闭,这可能会给您提示。这个问题很常见,编译器通常会添加这样一行来自动调试构建。但并非总是如此。
  • @Christopher 是的,问题的关键在于创建一个表达式来精确地做到这一点。
  • 忘记在表达式中这样做。在实际的控制台程序代码中执行此操作。这就是它一直属于的地方。
  • @Christopher 你有没有考虑过-。这是出于学术目的(学习)还是 2。这是一个更加复杂的场景的简化版本?
  • @Christopher 我没有任何控制台代码。 c# 代码在运行时使用表达式编译,这意味着控制台应用程序是一个完全不同的程序

标签: c# linq lambda


【解决方案1】:

编写类似于每个表达式的实际代码时,很容易看到发生了什么。

对于第一个:

Action<string[]> firstDelegate = parameterName => Console.ReadLine();

第二个:

Action<string[]> firstDelegate = parameterName => parameterName => Console.Readline();

因此,当您调用第一个委托时,它会从控制台读取一行。当你调用第二个委托时,它会创建一个新的 lambda,然后什么都不做。

如果你想创建一个从控制台读取一行的委托,那么你的第一个 sn-p 正是你应该做的。在这种情况下,没有理由在 lambda 中创建 lambda。

【讨论】:

  • 好的,感谢您的快速回复。但是我怎样才能在周围的 lambda 中执行创建的 lambda?有没有不同的表达方式?我一直认为创建这样的 lambda 会自动执行它,但那是错误的 :)
  • @ShinuSha_ 当您无法创建第二个 lambda 时,没有理由创建 lambda 并调用它。它没有生产力。不,创建 lambda 不会调用它,它只是创建它。创建 lambda 时自动调用它是没有意义的;首先创建 lambda 的唯一原因是因为您不想立即调用它(其目的是将调用推迟到以后)。
  • 是的,没错。添加额外的 lambda 是没有意义的。但是,我正在检索一个我不知道其精确委托类型的 lambda 实例(仅它的参数是字符串 [])。因此,通过嵌套它,我可以创建一个适合控制台应用程序 Main 方法委托的 lambda。
  • @ShinuSha_ 但这并没有解决你的问题。通过包装代码以创建您不知道的类型的委托以创建您知道的类型的委托,您没有做任何有用的事情。您要么需要弄清楚您实际获得的委托的类型是什么,要么您需要在不知道类型是什么的情况下调用它。将其包装在另一个 lambda 中并不能帮助您做任何这些事情。
  • 它不能解决知道类型的问题,但好在我不需要,因为控制台应用程序方法返回是无效的。 (但你是对的,将来我会检查类型。唯一的问题是目前限制用户使用正确的委托类型有点复杂。但对于控制台应用程序,返回类型对我来说真的无关紧要,从某种意义上说它比它没有更好的工作 - >如果用户想要返回一个错误代码,他应该使用正确的类型,如果不是我将包装它以便它仍然有效)
猜你喜欢
  • 1970-01-01
  • 2021-03-30
  • 2010-09-14
  • 2015-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多