2011-09-19 48 views
5

我剛剛瞭解到了VB.NET中靜態局部變量的用法,並想知道它在延遲加載屬性中的潛在用法。在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類來獲得(就我所知)相同的行爲。

現在,讓我們看看使用靜態變量的屬性。

Public Class Bar 

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

據我所看到的,這有幾個優點在通常的實現,主要你不能訪問變量的屬性外,還有不必使用一個額外的變量。

我對你的問題是:這些是「正確」的方法嗎?我知道靜態變量有額外的開銷,但以我個人的觀點來看,創建一個更容易被濫用的代碼會更容易嗎?與「傳統」方法相比,您失去了多少性能?與大型工廠相比,小班教學有何重要意義?

在此先感謝。

回答

3

靜態關鍵字有相當多的開銷,編譯器生成一大塊IL來實現它。它是什麼確實這樣做你的第一個片段沒有做的是確保線程不會導致問題。如果這不是一個問題,那麼你的第一個片段是lot更便宜。不僅僅是因爲它有更少的IL,而且因爲它會被內聯。由於包含Try/Finally代碼,因此帶Static的getter將永遠不會被內聯。

如果你的目標是.NET 4,那麼你絕對應該看看Lazy(Of T)類。

+0

+1同意,特別是在看什麼靜態生成後。 – tcarvin

+0

來自Hans Passant的其他人的參考資料[這裏是另一個答案](http://stackoverflow.com/a/12202349/4889167),詳細介紹。 –

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