0

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

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

3 回答 3

1

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

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

于 2012-05-30T21:09:32.743 回答
1

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


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

于 2012-05-17T22:56:55.427 回答
-1

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

于 2012-05-17T23:14:58.227 回答