Allow instance variables to be declared with scope of just a property declaration
I often use instance level variables as backing storage for properties.
I also try to lazy load these as often as possible.
ie in the property getter if the instance level variable is null I retrieve the data, set it into the instance-level variable and then return the variable:
private Customer customer;
public Customer Customer
{
get
{
if (customer == null)
{
customer = Repository.GetCustomer();
}
return customer;
}
}
However, if I need to refer to the Customer elsewhere in the class I have to remember to access it through the getter otherwise it will not be instantiated. Other developers often don't realise this and incorrectly access the instance variable directly.
I suggest that it be possible to declare variables that persist for the lifetime of the instance, which are only accessible in the property getter/setter e.g:
public Customer Customer
{
private Customer customer;
get
{
if (customer == null)
{
customer = Repository.GetCustomer();
}
return customer;
}
}
7 comments
-
antidemon
commented
As much as I don't want to vote against my own idea...since I raised this I have discovered the Lazy class.
Using this effectively removes my issue:public class Test
{
private Lazy<Customer> customer;public Test()
{
new Lazy<Customer>(() => Repository.GetCustomer());
}public Customer Customer
{
get
{
return customer.Value;
}
}
} -
chha
commented
Fully agree with Antidemon, Qwerty and Darin, and me I also need it in VB.NET, and not only within properties but but also within methods.
I didn't know this proposals already exists and wanted to propose even the same syntax as Qwerty did: a "this.variableName" (C#) and "Me._VariableName" (VB.NET).
@Andrew Teebay: Yes, this keyword still exists and No, hardly one can use it because it generates an enormous overhead with locking (everytime the variable is accessed, not only when it is initialized!!!) so that it is no alternative.
If someone is interested, that's what the VB-compiler generates when a "Static" is used:
'Original:
Public Class Class1Private ReadOnly Property Prop1 As Int32
Get
Static Dim myResult As Int32 = 25
myResult += 1
Return myResult
End Get
End PropertyEnd Class
'What the compiler generates: (decompiled with reflector)
Public Class Class1Private $STATIC$get_Prop1$2008$myResult As Integer
Private $STATIC$get_Prop1$2008$myResult$Init As StaticLocalInitFlag = New StaticLocalInitFlagPrivate ReadOnly Property Prop1 As Integer
Get
Monitor.Enter(Me.$STATIC$get_Prop1$2008$myResult$Init)
Try
If (Me.$STATIC$get_Prop1$2008$myResult$Init.State = 0) Then
Me.$STATIC$get_Prop1$2008$myResult$Init.State = 2
Me.$STATIC$get_Prop1$2008$myResult = &H19
ElseIf (Me.$STATIC$get_Prop1$2008$myResult$Init.State = 2) Then
Throw New IncompleteInitialization
End If
Finally
Me.$STATIC$get_Prop1$2008$myResult$Init.State = 1
Monitor.Exit(Me.$STATIC$get_Prop1$2008$myResult$Init)
End Try
Me.$STATIC$get_Prop1$2008$myResult += 1
Return Me.$STATIC$get_Prop1$2008$myResult
End Get
End PropertyEnd Class
'What we need:
Public Class Class1Private $$get_Prop1$2008$myResult As Integer = 25
Private ReadOnly Property Prop1 As Int32
Get
Me.$$get_Prop1$2008$myResult += 1
Return Me.$$get_Prop1$2008$myResult
End Get
End PropertyEnd Class
Thank you
-
Keiichi Iguchi commented
I like it too.
Additionally, I suggest [Cacheable] attribute that[Cacheable]
public Custmer Customer {
get {
customer = Repository.GetCustomer();
}
}automatically expands to like your code.
-
CSharpJohn
commented
-
Qwertie
commented
This concept is not specific to properties; it's best to think of this as a method-local member variable. I have often needed to define variables that are used by only one method in a class, so I could imagine a syntax like
void Foo() {
class int _bar;
// OR EVEN
int this._bar;
...
} -
Darin
commented
@Andrew: This concept is nothing like the DIM statement in VB, dim without without static can be used at several scopes.
I COMPLETELY SECOND this idea for both C# and VB.
The idea in vb is like this:
Public property Test() as integer
Private _Test as integer <---- note that this variable would be scoped only within this property. It wouldn't be visible outside the GET and SET.
Get Test
blah
End Get
Set Test(Value as Integer)
blah
End Set
End PropertyIn this way, the instance variables necessary for handling this property don't muck up the class level scope, they're completely isolated to the property. This also forces the rest of the code in the class to access the backing variable through the property, and not directly, which is very often a necessity and the cause of difficult to hunt down bugs when not done.
-
Andrew Teebay commented
This sounds a little like the old VB Dim Static ( not to be confused with VB Shared or C# Static) that did (and I think still does) exactly what you're asking. Why it's not available in C# I don't know. Maybe because they already used the key word static they just could not think of a word to use.