I just recently learned about the uses of static local variables in VB.NET and wondered about it's potential use in lazy loading properties.
Consider the following example code.
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
This would be a usual, simplified lazy-loading property. You may even want to use the generic Lazy Class to get (as far as i know) the same behaviour.
Now, let's look at the property while using a 开发者_如何学Cstatic variable.
Public Class Bar
Public ReadOnly Property FooImplementation As IFoo
Get
Static _fooImplementation as IFoo = New Foo
Return _fooImplementation
End Get
End Property
End Class
As far as i can see, this has a few advantages over the usual implementation, primary your inability to access the variable outside of the property, as well as not having to use an additional variable.
My question to you is: Which of those is the "right" way to do it? I know that static variables have additional overhead, but is it bad enough to create, in my personal opinion, unclearer code that can be misused easier? How much performance do you lose compared to the "traditional" method? How does it matter for small classes compared to huge factories?
Thanks in advance.
The Static keyword has rather a lot of overhead, the compiler generates a big chunk of IL to implement it. What it does do that your 1st snippet doesn't do is ensure that threading doesn't cause problems. If that is not a concern then your 1st snippet is a lot cheaper. Not just because it has a lot less IL but also because it will be inlined. A getter with Static will never be inlined since it contains Try/Finally code.
If you are targeting .NET 4 then you definitely should take a look at the Lazy(Of T) class.
That question was interesting enough for me to find the answer...how exactly does VB.NET implement static. Here's a 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();
}
}
精彩评论