有没有办法约束匿名函数参数的范围?

时间:2012-05-17 22:52:54

标签: c# .net c#-4.0 closures anonymous-function

我有一个采用匿名函数参数的方法。此函数的参数由局部变量提供。

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();

3 个答案:

答案 0 :(得分:1)

不幸的是*,这是不可能的。你几乎无法控制方法对其参数的作用。如果你没有使用泛型类型,那么就可以解决这个问题,但是你是这样,所以不要担心这种情况。 (我希望你不必。)


*实际上,我认为它“幸运”。这不是我们在这里讨论的C ++。

答案 1 :(得分:1)

如果T是结构,则包含类型T的字段或类型T[]的数组的代码可以将字段或数组元素作为外部方法的ref参数;该方法可以在该字段或数组插槽上直接有效地操作,而无需制作结构的临时副本,但是一旦返回该方法,保持字段或数组的类型就可以确信外部代码无法再访问该插槽。当然,Outside可以复制字段或元素的内容,但是除非或者直到持有结构的类型再次暴露给外部代码,否则它将无法更改原始文件。

不幸的是,如果T是一个可变类,那么公开引用将允许外部代码进行混杂复制并永远传递该引用。出于这个原因,可变类比可变结构更糟糕的数据持有者。如果想要允许外部代码在不暴露直接引用的情况下使用类,则需要创建包装类和接口。不幸的是,如果不使用真正可怕的重复代码,或者使用Reflection在运行时生成包装器,就无法做到这一点。

答案 2 :(得分:-1)

我认为你的代码已经做了你想要的。 代表lambda item => capturedInstance = item的委托仅传递给DoSomething<Foo>,并且该引用不会分发给任何其他人。因此,当包含方法完成时,委托将超出范围。 lambda表达式捕获的局部变量也是如此。 只有当您传递对代理的引用时,才会获得所需的行为。