Gri*_*ios 6 c# lambda local-variables memory-address
考虑以下代码:
private unsafe void Function()
{
int length;
// This line raises error CS1686, "Local 'length' or its members cannot have their address taken and be used inside an anonymous method or lambda expression".
glGetProgramiv(1, GL_PROGRAM_BINARY_LENGTH, &length);
FunctionWithLambda(() => Console.WriteLine(length));
}
private void FunctionWithLambda(Action callback)
{
callback();
}
Run Code Online (Sandbox Code Playgroud)
length请注意,我获取(局部变量)的地址,然后在 lambda 中使用该变量本身(而不是其地址)。我理解为什么局部变量地址不能直接在 lambda 中使用(参见为什么不能将变量的地址传递给匿名函数?等示例),但是为什么我不能使用一次分配的值length(即使该赋值碰巧使用了&运算符)?错误 CS1686 的官方文档(https://learn.microsoft.com/bs-latn-ba/dotnet/csharp/misc/cs1686)尚未澄清这种混乱。
我的假设是,这只是一种语言限制,但我很好奇是否有我遗漏的潜在技术原因。另请注意,我不是问如何解决这个问题(我知道我可以length先轻松复制到另一个局部变量)。
C# 规范规定如下 (我的粗体):
\n\n\n23.4 固定变量和可移动变量
\n地址运算符(\xc2\xa723.6.5) 和
\nfixed语句 (\xc2\xa723.7) 将变量分为两类:
\n固定变量和可移动变量。...剪断...
\n运算
\n&符(\xc2\xa723.6.5)允许不受限制地获取固定变量的地址。但是,由于可移动变量会被垃圾收集器重定位或处置,因此只能使用fixed语句(\xc2\xa723.7) 来获取可移动变量的地址,并且该地址仅在该语句的持续时间内保持有效。fixed陈述。准确地说,固定变量是以下之一:
\n\n
\n- 由引用局部变量、值参数或参数数组的简单名称 (\xc2\xa712.7.3) 生成的变量,除非该变量由匿名函数 (\xc2\xa712.16.6.2) 捕获。
\n- ……
\n
所以它是规范明确禁止的。至于为什么禁止它,你必须询问语言设计者,但考虑到捕获变量涉及多少复杂性,这在某种程度上是合乎逻辑的。
\n