在VB.NET中的延迟加载属性中使用静态局部变量

时间:2011-09-19 17:17:48

标签: vb.net static lazy-loading

我刚刚了解了VB.NET中静态局部变量的用法,并想知道它在延迟加载属性中的潜在用途。

考虑以下示例代码。

Public Class Foo
  Implements IFoo
End Class

Public Interface IFoo
End Interface

Public Class Bar

  Private _fooImplementation As IFoo
  Public ReadOnly Property FooImplementation As IFoo
    Get
      If _fooImplementation Is Nothing Then _fooImplementation = New Foo
      Return _fooImplementation
    End Get
  End Property
End Class

这将是一个通常的,简化的延迟加载属性。您甚至可能希望使用通用的Lazy Class来获取(据我所知)相同的行为。

现在,让我们在使用静态变量时查看属性。

Public Class Bar

  Public ReadOnly Property FooImplementation As IFoo
    Get
      Static _fooImplementation as IFoo = New Foo
      Return _fooImplementation
    End Get
  End Property
End Class

据我所知,这比通常的实现有一些优点,主要是你无法访问属性之外的变量,以及不必使用额外的变量。

我的问题是:哪些是“正确”的方式呢?我知道静态变量有额外的开销,但是在我个人看来,创建可能被滥用的不清除代码是否足够糟糕?与“传统”方法相比,您失去了多少性能?与大型工厂相比,小班级如何重要?

提前致谢。

2 个答案:

答案 0 :(得分:3)

Static 关键字有很多开销,编译器会生成一大块IL来实现它。 所做的做的事情是你的第一个片段不能确保线程不会导致问题。如果这不是一个问题,那么你的第一个片段就是很多更便宜。不仅因为它的IL少得多,而且因为它将被内联。带静态的getter永远不会被内联,因为它包含Try / Finally代码。

如果您的目标是.NET 4,那么你一定要看看Lazy(Of T)类。

答案 1 :(得分:1)

这个问题很有趣,我找到了答案...... VB.NET究竟是如何实现静态的。这是一个C#equivilent:

public class Bar
  {
    [SpecialName]
    private IFoo \u0024STATIC\u0024get_FooImplementation\u0024200122C\u0024_fooImplementation;
    [SpecialName]
    private StaticLocalInitFlag \u0024STATIC\u0024get_FooImplementation\u0024200122C\u0024_fooImplementation\u0024Init;

    public IFoo FooImplementation
    {
      get
      {
        Monitor.Enter((object) this.\u0024STATIC\u0024get_FooImplementation\u0024200122C\u0024_fooImplementation\u0024Init);
        try
        {
          if ((int) this.\u0024STATIC\u0024get_FooImplementation\u0024200122C\u0024_fooImplementation\u0024Init.State == 0)
          {
            this.\u0024STATIC\u0024get_FooImplementation\u0024200122C\u0024_fooImplementation\u0024Init.State = (short) 2;
            this.\u0024STATIC\u0024get_FooImplementation\u0024200122C\u0024_fooImplementation = (IFoo) new Foo();
          }
          else if ((int) this.\u0024STATIC\u0024get_FooImplementation\u0024200122C\u0024_fooImplementation\u0024Init.State == 2)
            throw new IncompleteInitialization();
        }
        finally
        {
          this.\u0024STATIC\u0024get_FooImplementation\u0024200122C\u0024_fooImplementation\u0024Init.State = (short) 1;
          Monitor.Exit((object) this.\u0024STATIC\u0024get_FooImplementation\u0024200122C\u0024_fooImplementation\u0024Init);
        }
        return this.\u0024STATIC\u0024get_FooImplementation\u0024200122C\u0024_fooImplementation;
      }
    }

    [DebuggerNonUserCode]
    public Bar()
    {
      this.\u0024STATIC\u0024get_FooImplementation\u0024200122C\u0024_fooImplementation\u0024Init = new StaticLocalInitFlag();
    }
  }