2011-09-19 15 views
5

Recientemente descubrí los usos de las variables locales estáticas en VB.NET y me pregunté sobre su posible uso en las propiedades de carga diferida.Uso de variables locales estáticas en la propiedad de carga diferida en VB.NET

Considere el siguiente código de ejemplo.

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 

Esta sería una propiedad de carga diferida habitual y simplificada. Puede que quiera usar la Clase Lazy genérica para obtener (hasta donde yo sepa) el mismo comportamiento.

Ahora, veamos la propiedad mientras usamos una variable estática.

Public Class Bar 

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

Por lo que yo puedo ver, esto tiene algunas ventajas con respecto a la puesta en práctica habitual, primaria su incapacidad de acceder a la variable fuera de la propiedad, así como no tener que utilizar una variable adicional.

Mi pregunta es: ¿Cuál de esas es la forma "correcta" de hacerlo? Sé que las variables estáticas tienen una sobrecarga adicional, pero ¿es lo suficientemente malo como para crear, en mi opinión personal, un código más poco claro que pueda ser mal utilizado más fácilmente? ¿Cuánto rendimiento pierde en comparación con el método "tradicional"? ¿Cómo es importante para las clases pequeñas en comparación con las grandes fábricas?

Gracias de antemano.

Respuesta

3

La palabra clave Estática tiene bastante sobrecarga, el compilador genera una gran cantidad de IL para implementarla. Lo que hace que su primer fragmento no hace es asegurarse de que el enhebrado no cause problemas. Si eso no es una preocupación, entonces su primer fragmento es un lote más barato. No solo porque tiene mucho menos IL, sino también porque estará en línea. Un getter con Static nunca se incluirá porque contiene el código Try/Finally.

Si está apuntando a .NET 4, entonces definitivamente debe echar un vistazo a la clase Lazy (Of T).

+0

+1 De acuerdo, especialmente después de ver lo que genera estática. – tcarvin

+0

Para referencia de otros, [aquí hay otra respuesta] (http://stackoverflow.com/a/12202349/4889167) de Hans Passant que entra en más detalles. –

1

Esa pregunta fue lo suficientemente interesante como para encontrar la respuesta ... ¿cómo exactamente implementa VB.NET estática. Aquí hay un equivalente de C#:

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