用于生成共享相同闭包变量的匿名委托的C#技术

FMM*_*FMM 6 c# lambda anonymous-methods

我有一种情况需要生成一些类似的匿名代表.这是一个例子:

public void Foo(AnotherType theObj)
{
    var shared = (SomeType)null;

    theObj.LoadThing += () =>
    {
        if(shared == null)
            shared = LoadShared();

        return shared.Thing;
    };

    theObj.LoadOtherThing += () =>
    {
        if(shared == null)
            shared = LoadShared();

        return shared.OtherThing;
    };

    // more event handlers here...
}
Run Code Online (Sandbox Code Playgroud)

我遇到的麻烦是我的代码不是很干.每个事件处理程序的内容非常相似,可以很容易地参数化为工厂方法.阻止我这样做的唯一因素是每个委托需要共享对shared变量的引用.我无法shared使用ref关键字传递给工厂方法,因为您无法围绕ref变量创建闭包.有任何想法吗?

Eri*_*ert 18

没有任何问题无法通过添加更多抽象来解决.(*)

你反复重复的模式是"延迟加载"模式.这种模式非常适合在一种类型中被捕获,事实上,它已经在框架的第4版中被捕获.文档在这里:

http://msdn.microsoft.com/en-us/library/dd642331.aspx

然后你可以这样做:

public void Foo(AnotherType theObj)
{
    var shared = new Lazy<SomeType>(()=>LoadShared());
    theObj.LoadThing += () => shared.Value.Thing;
    theObj.LoadOtherThing += () => shared.Value.OtherThing;
    // more event handlers here...
}
Run Code Online (Sandbox Code Playgroud)

你去吧 第一次shared.Value访问值被加载; 每次后续使用缓存值.额外奖励:如果在多个线程上访问共享值,这甚至是线程安全的.(有关我们对螺纹安全的确切保证的详细信息,请参阅文档.)


(*)当然除了问题"我有太多的抽象."

  • @phoog:解决暂停问题所需的抽象传统上称为"oracle".问题是,使用我们现在拥有的任何工艺都无法实现神谕. (4认同)