例如,

public int DoSomething(in SomeType something){
  int local(){
     return something.anInt;
  }
  return local();
}

为什么编译器会发出一个错误,说明Something变量不能在局部函数中使用?

推荐答案

有关本地函数的文档说明如下

Variable capture

请注意,当局部函数捕获封闭作用域中的变量时,局部函数将作为委托类型实现.

看看Lambdas:

Capture of outer variables and variable scope in lambda expressions

Lambda表达式不能直接从封闭方法捕获inrefout参数.

原因很简单:由于有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属性.哎呀.

"您不能在委托中捕获引用参数(inoutref)"规则可防止此问题.

您可以通过复制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
}

Csharp相关问答推荐

为什么在GuardationRule的收件箱函数中,decode.TryParse(valueString,out valueParsed)在给出1.0.1时返回true?

更改对象的旋转方向

C#类主构造函数中的调试参数

为什么我不能更改尚未设置的模拟对象属性的值?

ASP.NET MVC购物车数量更新并从购物车中删除项目

C#自定义字典与JSON(de—)serialize

XUNIT是否使用测试数据的源生成器?

Quartz调度程序不调用作业(job)类

使用HttpResponseMessage中的嵌套列表初始化JSON

MigraDoc文档

带有列表参数的表达式树

在implementationFactory中避免循环依赖

C#动态设置ServerReport报表参数

用C#从XML内部元素中获取特定值

如何在一次数据库调用中为ASP.NET核心身份用户加载角色

SignalR跨域

C#-如何将int引用获取到byte[]

客户端/服务器RPC如何处理全局变量?

从实例扩展中调用类型的扩展方法

定义可以是两个类之一的类成员