为什么不能在lambda表达式中使用ref或out参数?
我今天遇到了错误并找到了解决方法,但我仍然很好奇为什么这是编译时错误.
CS1628:不能在匿名方法,lambda表达式或查询表达式中的ref或out参数'parameter'中使用
这是一个简单的例子:
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();
}
Run Code Online (Sandbox Code Playgroud)
Jar*_*Par 117
Lambda具有改变它们捕获的变量的生命周期的外观.例如以下lambda表达式引起的参数P1到活长于当前方法帧作为它的值可以在方法帧之后访问是不再在堆栈上
Func<int> Example(int p1) {
return () => p1;
}
Run Code Online (Sandbox Code Playgroud)
捕获变量的另一个属性是变量的变化在lambda表达式之外也是可见的.例如,以下打印42
void Example2(int p1) {
Action del = () => { p1 = 42; }
del();
Console.WriteLine(p1);
}
Run Code Online (Sandbox Code Playgroud)
这两个属性产生一组特定的效果,它们以下列方式面对ref参数
这些是一些不兼容的属性,也是lambda表达式中不允许它们的原因之一.
Meh*_*ari 81
在引擎盖下,匿名方法是通过提升捕获的变量(这是你的问题主体所有)来实现的,并将它们存储为编译器生成的类的字段.无法将参数ref
或out
参数存储为字段.Eric Lippert在博客文章中对此进行了讨论.请注意,捕获的变量和lambda参数之间存在差异.您可以拥有如下所示的"形式参数",因为它们不是捕获的变量:
delegate void TestDelegate (out int x);
static void Main(string[] args)
{
TestDelegate testDel = (out int x) => { x = 10; };
int p;
testDel(out p);
Console.WriteLine(p);
}
Run Code Online (Sandbox Code Playgroud)
Ben*_*ams 63
您可以但必须明确定义所有类型
(a, b, c, ref d) => {...}
Run Code Online (Sandbox Code Playgroud)
但是,无效
(int a, int b, int c, ref int d) => {...}
Run Code Online (Sandbox Code Playgroud)
已验证
因为这是Google上"C#lambda ref"的最佳结果之一; 我觉得我需要扩展上面的答案.旧的(C#2.0)匿名委托语法有效,它确实支持更复杂的签名(以及闭包).Lambda和匿名委托至少在编译器后端共享感知实现(如果它们不相同) - 最重要的是,它们支持闭包.
我在搜索时尝试做的事情,以演示语法:
public static ScanOperation<TToken> CreateScanOperation(
PrattTokenDefinition<TNode, TToken, TParser, TSelf> tokenDefinition)
{
var oldScanOperation = tokenDefinition.ScanOperation; // Closures still work.
return delegate(string text, ref int position, ref PositionInformation currentPosition)
{
var token = oldScanOperation(text, ref position, ref currentPosition);
if (token == null)
return null;
if (tokenDefinition.LeftDenotation != null)
token._led = tokenDefinition.LeftDenotation(token);
if (tokenDefinition.NullDenotation != null)
token._nud = tokenDefinition.NullDenotation(token);
token.Identifier = tokenDefinition.Identifier;
token.LeftBindingPower = tokenDefinition.LeftBindingPower;
token.OnInitialize();
return token;
};
}
Run Code Online (Sandbox Code Playgroud)
请记住,Lambdas在程序上和数学上更安全(因为前面提到的ref值促销):你可能会打开一堆蠕虫.使用此语法时请仔细考虑.
归档时间: |
|
查看次数: |
77327 次 |
最近记录: |