无法在 lambda 表达式中使用 ref 或 out 参数
为什么不能在 lambda 表达式中使用 ref 或 out 参数?
我今天遇到了这个错误并找到了解决方法,但我仍然很好奇为什么这是一个编译时错误。
CS1628:不能在 ref 或 out 参数中使用匿名方法、lambda 表达式或查询表达式中的参数'
下面是一个简单的示例:
private void Foo()
{
int value;
Bar(out value);
}
private void Bar(out int value)
{
value = 3;
int[] array = { 1, 2, 3, 4, 5 };
int newValue = array.Where(a => a == value).First();
}
Why can't you use a ref or out parameter in a lambda expression?
I came across the error today and found a workaround but I was still curious why this is a compile-time error.
CS1628: Cannot use in ref or out parameter 'parameter' inside an anonymous method, lambda expression, or query expression
Here's a simple example:
private void Foo()
{
int value;
Bar(out value);
}
private void Bar(out int value)
{
value = 3;
int[] array = { 1, 2, 3, 4, 5 };
int newValue = array.Where(a => a == value).First();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
Lambda 看起来会改变它们捕获的变量的生命周期。例如,以下 lambda 表达式导致参数 p1 的生存时间比当前方法框架的时间长,因为在方法框架不再位于堆栈上后可以访问其值。
捕获变量的另一个属性是更改变量在 lambda 表达式之外也是可见的。例如,以下代码打印出 42
这两个属性会产生一组特定的效果,这些效果会以下列方式与
ref
参数发生冲突:ref
参数可能具有固定的寿命。考虑将局部变量作为 ref 参数传递给函数。这些属性有些不兼容,也是 lambda 表达式中不允许使用它们的原因之一。
Lambdas have the appearance of changing the lifetime of variables that they capture. For instance, the following lambda expression causes the parameter p1 to live longer than the current method frame as its value can be accessed after the method frame is no longer on the stack
Another property of captured variables is that changes to the variables are also visible outside the lambda expression. For example, the following code prints out 42
These two properties produce a certain set of effects which fly in the face of a
ref
parameter in the following ways:ref
parameters may have a fixed lifetime. Consider passing a local variable as aref
parameter to a function.ref
parameter itself. Both within the method and in the caller.These are somewhat incompatible properties and are one of the reasons they are disallowed in lambda expressions.
在幕后,匿名方法是通过提升捕获的变量(这就是您的问题正文的全部内容)并将它们存储为编译器生成的类的字段来实现的。无法将
ref
或out
参数存储为字段。 Eric Lippert 在 博客条目。请注意,捕获的变量和 lambda 参数之间存在差异。您可以拥有如下所示的“形式参数”,因为它们不是捕获的变量:Under the hood, the anonymous method is implemented by hoisting captured variables (which is what your question body is all about) and storing them as fields of a compiler generated class. There is no way to store a
ref
orout
parameter as a field. Eric Lippert discussed it in a blog entry. Note that there is a difference between captured variables and lambda parameters. You can have "formal parameters" like the following as they are not captured variables:您可以,但必须显式定义所有类型,因此
无效,但是
有效
You can but you must explicitly define all the types so
Is invalid, however
Is valid
也许这个?
And maybe this?
您不能直接在 lambda 表达式中使用 out 参数。其他答案中解释了您不能这样做的原因。
解决方法
But you can use a local temporary variable with for the inner function and, after the inner function has been executed, assign the out value from the inner function to the out value of the outer function:
请注意
这个问题是在 2009 年创建的。我的答案是在 2023 年使用 C#10 和 .NET 6 创建的。我不知道这个答案是否也在 2009 年起作用,这意味着,这里的代码可能依赖于 C# 和 的增强.NET 可能是同时创建的。
You can not use an out parameter directly in a lambda expression. The reason why you can not do that is explained in the other answers.
Workaround
But you can use a local temporary variable with for the inner function and, after the inner function has been executed, assign the out value from the inner function to the out value of the outer function:
Please note
The question was created in 2009. My answer was created in 2023 using C#10 and .NET 6. I don't know whether this answer had also worked back in 2009, which means, the code here might depend on enhancements to C# and .NET that might have been made in the meantime.
我再举一个例子。
描述
下面的代码将抛出此错误。因为lambda表达式
(i)=>{...}
带来的变化只在函数test
中起作用。解决方案
因此,如果您删除参数的
out
,它就会起作用。如果您确实需要
out
,请不要直接更改 lambda 表达式中的参数。相反,请使用临时变量。I will give you another example.
Description
The code below will throw out this error. Because the change brought by the lambda expression
(i)=>{...}
only works in the functiontest
.Solution
So, if you remove
out
of the parameter, it works.If you need
out
really, don't change the parameter in the lambda expression directly. Instead, use a temporary variable please.