我刚刚了解了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
据我所知,这比通常的实现有一些优点,主要是你无法访问属性之外的变量,以及不必使用额外的变量。
我的问题是:哪些是“正确”的方式呢?我知道静态变量有额外的开销,但是在我个人看来,创建可能被滥用的不清除代码是否足够糟糕?与“传统”方法相比,您失去了多少性能?与大型工厂相比,小班级如何重要?
提前致谢。
答案 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();
}
}