例如,
public int DoSomething(in SomeType something){
int local(){
return something.anInt;
}
return local();
}
为什么编译器会发出一个错误,说明Something变量不能在局部函数中使用?
例如,
public int DoSomething(in SomeType something){
int local(){
return something.anInt;
}
return local();
}
为什么编译器会发出一个错误,说明Something变量不能在局部函数中使用?
有关本地函数的文档说明如下
请注意,当局部函数捕获封闭作用域中的变量时,局部函数将作为委托类型实现.
看看Lambdas:
Capture of outer variables and variable scope in lambda expressions个
Lambda表达式不能直接从封闭方法捕获
in
、ref
或out
参数.
原因很简单:由于有ref
个转义问题,不可能将这些参数提升到一个类中.这就是为了捕捉到它而必须做的事情.
public Func<int> DoSomething(in SomeType something){
int local(){
return something.anInt;
}
return local;
}
假设此函数的调用方式如下:
public Func<int> Mystery()
{
SomeType ghost = new SomeType();
return DoSomething(ghost);
}
public void Scary()
{
var later = Mystery();
Thread.Sleep(5000);
later(); // oops
}
Mystery
函数创建ghost
并将其作为in
参数传递给DoSomething
,这意味着它将作为对ghost
变量的只读引用传递.
DoSomething
函数将此引用捕获到本地函数local
中,然后将该函数作为Func<int>
委托返回.
当Mystery
函数返回时,ghost
变量不再存在.然后,Scary
函数使用委托来调用local
函数,local
将try 从不存在的变量中读取anInt
属性.哎呀.
"您不能在委托中捕获引用参数(in
、out
、ref
)"规则可防止此问题.
您可以通过复制in
参数并捕获该副本来解决此问题:
public Func<int> DoSomething2(in SomeType something){
var copy = something;
int local(){
return copy.anInt;
}
return local;
}
请注意,返回的委托在copy
上操作,而不是在原始ghost
上操作.这意味着代理将始终具有有效的copy
以从中获得anInt
.然而,这意味着future 对ghost
的任何更改都不会对copy
产生影响.
public int Mystery()
{
SomeType ghost = new SomeType() { anInt = 42 };
var later = DoSomething2(ghost);
ghost = new SomeType() { anInt = -1 };
return later(); // returns 42, not -1
}