I have been working to make some code more efficient, and I am wondering now which pattern is the more efficient. The solution has code in both VB.NET and C# for legacy reasons.
I have put in the VB and C# versions of the two approaches that we have.
The idea is that if the Foo property is accessed and _foo is null, then it will be set to a new object, and any subsequent requests will access that same object and not create a new one each time.
I know that the compiler and JIT do some smart things under the bonnet, but I am not sure which is the more efficient way of doing things.
Option 1: Coalesce the value. Visual Studio keeps recommending coalescence in places, so this makes me think that that operation is quite optimised. However, this does assign to _foo each time we get Foo
Option 2: Do the comparison of _foo and null and then only assign to _foo if needed.
I'm sure that there is barely any difference between the two in speed, but I am curious about how these are treated at the much lower level
Private _foo As List(Of Fubar)
Private _bar As String
Private _foo2 As List(Of Fubar)
Private _bar2 As String
Public Property Foo As List(Of Fubar)
Get
_foo = If(_foo, New List(Of Fubar))
Return _foo
End Get
Set (value As List(Of Fubar))
_foo = value
End Set
End Property
Public Property Bar As String
Get
_bar = If(_bar, String.Empty)
Return _bar
End Get
Set (value As String)
_bar = value
End Set
End Property
Public Property Foo2 As List(Of Fubar)
Get
If _foo2 Is Nothing Then _foo2 = New List(Of Fubar)
Return _foo2
End Get
Set (value As List(Of Fubar))
_foo2 = value
End Set
End Property
Public Property Bar2 As String
Get
If _bar2 Is Nothing Then _bar2 = String.Empty
Return _bar2
End Get
Set (value As String)
_bar2 = value
End Set
End Property
private List<Fubar> _foo;
private string _bar;
private List<Fubar> _foo2;
private string _bar2;
public List<Fubar> Foo
{
get
{
_foo = (_foo ?? new List<Fubar>());
return _foo;
}
set
{
_foo = value;
}
}
public string Bar
{
get
{
_bar = (_bar ?? string.Empty);
return _bar;
}
set
{
_bar = value;
}
}
public List<Fubar> Foo2
{
get
{
if (_foo2 == null) { _foo2 = new List<Fubar>(); }
return _foo2;
}
set
{
_foo2 = value;
}
}
public string Bar2
{
get
{
if (_bar2 == null) { _bar2 = string.Empty; }
return _bar2;
}
set
{
_bar2 = value;
}
}
Here we go; the
IsEmptyhere is telling us whether it wasnullbefore thegetoperation, i.e. which branch did it take.My conclusion:
*2approach is betterPersonally, in C# I prefer:
I'll add a timing for that... (edit: that is
Foo3/Bar3and it looks to be a marginal improvement onFoo2/Foo3).Note I removed the actual
List<T>creation to avoid overhead - it assigns to a static now.Code: