我有一个采用匿名函数参数的方法。此函数的参数由局部变量提供。
public void DoSomething<T>(Action<T> method) where T : new()
{
T instance = new T();
method.Invoke(instance);
}
我想阻止创建一个闭包。 DoSomething<T>
完成后,局部变量应超出范围。有没有办法在编译时限制它?
以下是我想避免的情况:
Foo capturedInstance = null;
DoSomething<Foo>(item => capturedInstance = item);
capturedInstance.Call();
答案 0 :(得分:1)
不幸的是*,这是不可能的。你几乎无法控制方法对其参数的作用。如果你没有使用泛型类型,那么就可以解决这个问题,但是你是这样,所以不要担心这种情况。 (我希望你不必。)
*实际上,我认为它“幸运”。这不是我们在这里讨论的C ++。
答案 1 :(得分:1)
如果T
是结构,则包含类型T
的字段或类型T[]
的数组的代码可以将字段或数组元素作为外部方法的ref
参数;该方法可以在该字段或数组插槽上直接有效地操作,而无需制作结构的临时副本,但是一旦返回该方法,保持字段或数组的类型就可以确信外部代码无法再访问该插槽。当然,Outside可以复制字段或元素的内容,但是除非或者直到持有结构的类型再次暴露给外部代码,否则它将无法更改原始文件。
不幸的是,如果T
是一个可变类,那么公开引用将允许外部代码进行混杂复制并永远传递该引用。出于这个原因,可变类比可变结构更糟糕的数据持有者。如果想要允许外部代码在不暴露直接引用的情况下使用类,则需要创建包装类和接口。不幸的是,如果不使用真正可怕的重复代码,或者使用Reflection在运行时生成包装器,就无法做到这一点。
答案 2 :(得分:-1)
我认为你的代码已经做了你想要的。
代表lambda item => capturedInstance = item
的委托仅传递给DoSomething<Foo>
,并且该引用不会分发给任何其他人。因此,当包含方法完成时,委托将超出范围。 lambda表达式捕获的局部变量也是如此。
只有当您传递对代理的引用时,才会获得所需的行为。