Access member variable directly or through property within the class it is defined?

C

CMM

"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNOSPAM> wrote in message
the class is modified later. Suppose we have an uninitialized
ArrayList member variable and the accessor knows that it should
be created on first access. <snip>

I'm a strong advocate for initializing in the declaration (and so is MS in
their guidelines and the entire world outside of VB).

'arrays should be initialized
Private myArray As Integer() = {}

'objects should be initialized (most of the time)
Private myArrayList As New ArrayList

'and, yes, string objects should be initialized and not left as Nothing
'unless you actually need to do something particular with "Nothing."
Private myStr As String = String.Empty

This initialize-in-declaration is less less important IF you do NOT provide
a default New() and instead *require* parameters to be passed into it ( like
New(ary, arrayList, str) )
 
H

Herfried K. Wagner [MVP]

CMM said:
I'm a strong advocate for initializing in the declaration (and so is MS in
their guidelines and the entire world outside of VB).

'arrays should be initialized
Private myArray As Integer() = {}

'objects should be initialized (most of the time)
Private myArrayList As New ArrayList

'and, yes, string objects should be initialized and not left as Nothing
'unless you actually need to do something particular with "Nothing."
Private myStr As String = String.Empty

I think this depends on the particular case. Especially for strings an
empty string means something differently from a 'Nothing' reference. A
'Person' class with a 'FirstName' property of type 'String' could indicate
an unknown first name if the property is set to 'Nothing' and an empty (no)
first name if the property is set to an empty string.
 
C

CMM

Herfried K. Wagner said:
I think this depends on the particular case. Especially for strings an
empty string means something differently from a 'Nothing' reference. A
'Person' class with a 'FirstName' property of type 'String' could indicate
an unknown first name if the property is set to 'Nothing' and an empty
(no) first name if the property is set to an empty string.

Which is why I said "unless you actually need to do something particular
with 'Nothing.'" Nonetheless, I'd prefer to use DBNull in the scenerio you
outline. I have never (well, maybe once with XML files ;-) )had to use
Nothing.String for anything. Nothing does NOT mean "missing data"(!... well
it could if you as the programmer wanted it to).... it means "uninitialized
value."

From MSDN:
"The System.DBNull value indicates that the Object represents missing or
nonexistent data. DBNull is not the same as Nothing, which indicates that a
variable has not yet been initialized. DBNull is also not the same as a
zero-length string (""), which is sometimes referred to as a null string."
 
H

Herfried K. Wagner [MVP]

CMM said:
Which is why I said "unless you actually need to do something particular
with 'Nothing.'" Nonetheless, I'd prefer to use DBNull in the scenerio you
outline. I have never (well, maybe once with XML files ;-) )had to use
Nothing.String for anything. Nothing does NOT mean "missing data"(!...
well it could if you as the programmer wanted it to).... it means
"uninitialized value."

IMO it simply means "variable not pointing to an instance" without further
semantics. However, it's possible to assign further semantics to variables
pointing to 'Nothing'.
From MSDN:
"The System.DBNull value indicates that the Object represents missing or
nonexistent data. DBNull is not the same as Nothing, which indicates that
a variable has not yet been initialized. DBNull is also not the same as a
zero-length string (""), which is sometimes referred to as a null string."

I think the sentence "indicates that a variable not yet been initialized" is
unfortunate. Variables can even be initialized with 'Nothing' or can be set
to 'Nothing' later on while the program is executing. The documentation for
'Nothing' contains a more appropriate description: "If the variable is of a
reference type — that is, an object variable — 'Nothing' means the variable
is not associated with any object".

Using DBNull is not always an option, for example, it cannot be directly
assigned to a property of type 'String'. It's a pretty obvious observation
that 'DBNull.Value' is not the same as a 'Nothing' reference or an empty
string. BTW: I have rarely seen the term "null string" for a zero-length
(empty) string.
 
C

CMM

string. BTW: I have rarely seen the term "null string" for a zero-length
(empty) string.

Yeah. Me either.
NullString is yet ANOTHER thing... at least classically in VB.Classic...
where vbNullString is used to pass C null-terminated empty strings to API's.

I don't disagree with your NothingString comments either. But, I don't think
I have ever encountered a situation where a dependency set my strings back
to Nothing. IMO, NothingStrings' usefulness is extremely rare and
specialized. Using them or not taking care to avoid them leads to needless
fragility in complex applications. I'm NOT saying that they're useless....
just that their usefulness is rare.
 
J

Joergen Bech

"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNOSPAM> wrote in message


I'm a strong advocate for initializing in the declaration (and so is MS in
their guidelines and the entire world outside of VB).

I must go read that. Suppose the initializations are independent,
such as

Dim _myA As Integer = 2
Dim _myB As Integer = _myA * 2
Dim _myC As Integer = _myA + _myB

you cannot just change the order of declarations, but if that sequence
of initializations was made in a code block, you could swap them
around all you liked, as long as the sequence in the code block
remained the same.
'arrays should be initialized
Private myArray As Integer() = {}

'objects should be initialized (most of the time)
Private myArrayList As New ArrayList

Suppose we are dealing with a more complex (and expensive) object
which might not be needed during the lifetime of the instance of the
class. Would you want to initialize such an object at declaration time
or on first use? In VB6, "Dim X As New SomeObject" meant that the
instance X was only created if it was referenced - something that went
against the general recommendations for performance reasons
(every reference to X was wrapped in code checking for the existence
of X behind the scenes, which would bloat the compiled .exe), but for
*expensive* objects, I still think a similar pattern has its uses.

I think FxCop by default warns about unnecessary initialization, i.e.
Integer = 0, Boolean = False, etc. Something I'm not sure I agree
with, since I like all my initializations to be explicit - whether at
declaration time or in an initialization code block.

/JB
 
C

CMM

Suppose we are dealing with a more complex (and expensive) object
which might not be needed during the lifetime of the instance of the
class. Would you want to initialize such an object at declaration time
or on first use? In VB6, "Dim X As New SomeObject" meant that the
<snip>

The question to ask in that case is "why is this variable at the method
level?" Method level variables are usually the lazy programmers way of
passing around data (bad code!) instead of as parameters. Having said that,
I can see what you're saying. Like with everything else, no rule is
absolute. There are clearly cases (in Property Accessor/ Value variables)
where not initializing them is *intentionally* part of the design.

Keep in mind though that object creation (unless it does some creepy IO in
its constructor) is in no way expensive in VB.NET. A class with 1000 lines
of code takes the same amount of time to instantiate as a class with 2 lines
of code. (I'm talking method/code here, not data). VB.Classic had problems
because of ref counting and stuff like that.... but even back then the
"expense" of creating objects (as opposed to say structures) was way
overhyped IMO. In. .NET, the expense (even for big complex classes) is
virtually 0.

Inside methods, the pattern is even clearer. Objects should be Dim'd exactly
when they are needed rather than at the top of the method as was the
VB.Classic practice. If their reference is based on a conditional then it's
ok to create them unitialized and then set right afterwards. But if their
value is known and not condition based they should always be initialized.

Correct Usage Patterns (arguably)

Dim o As New SomeClass
---
Dim o As SomeClass = SomeObjA
---
Dim o As SomeClass
If someConditional Then
o = SomeObjA
Else
o = SomeObjB
End If
 
J

Joergen Bech

<snip>

The question to ask in that case is "why is this variable at the method
level?" Method level variables are usually the lazy programmers way of
passing around data (bad code!) instead of as parameters. Having said that,
I can see what you're saying. Like with everything else, no rule is
absolute. There are clearly cases (in Property Accessor/ Value variables)
where not initializing them is *intentionally* part of the design.

I was thinking about a usercontrol wrapping a tabcontrol with a number
of tabpages, each of which contains a usercontrol wrapping the
controls for that page. In some cases, initializing all pages at once
is desired (i.e. long wait the first time the tabcontrol is
displayed).
In other cases, we want to display the tabcontrol as quickly as
possible, but only initialize the individual tabpages as they are
being selected by the user.

Then, of course, there are the high-volume cases where tens of
thousands instances of a class need to be instantiated in a short
span of time and where every little unnecessary instantiation takes
time (e.g. if the instantiated object creates a new GUID or similar).

I agree with the rest of your statements about usage patterns inside
methods. I am only talking about the class' members.

/JB
 
C

CMM

--
-C. Moya
www.cmoya.com
Joergen Bech @ post1.tele.dk> said:
I was thinking about a usercontrol wrapping a tabcontrol with a number
of tabpages, each of which contains a usercontrol wrapping the
controls for that page. In some cases, initializing all pages at once
is desired (i.e. long wait the first time the tabcontrol is
displayed).
In other cases, we want to display the tabcontrol as quickly as
possible, but only initialize the individual tabpages as they are
being selected by the user.

Then, of course, there are the high-volume cases where tens of
thousands instances of a class need to be instantiated in a short
span of time and where every little unnecessary instantiation takes
time (e.g. if the instantiated object creates a new GUID or similar).

I agree with the rest of your statements about usage patterns inside
methods. I am only talking about the class' members.

/JB
 
C

CMM

Sorry... hit send too soon.

Anyway. I see what you mean. In the first example "the initialize as soon as
possible" idea doesn't extend to elements of a collection (your tab page
contents). Though it does apply to the collection instance itself (it can
instantiated, but empty and filled as needed). Forms and Controls are tricky
because Painting/Redraw is a big bottleneck as is the Win32 Messaging
Subsystem. That's why they have those SuspendLayout and BeginUpdate
mechanisms....

In the second example, there's no doubt some rare classes might necessitate
a first-use sort of mechanism on some of their Property Accessors and
underlying values... though I venture to say this is rarer than you think
and needs study before you actually spend time doing it. For instance....
using GUID your example.... on my machine and in debug mode it takes 15ms to
create 10,000 guid's and add them to an ArrayList! That's less than a blink
of an eye.
 
H

Herfried K. Wagner [MVP]

Joergen Bech @ post1.tele.dk> said:
In VB6, "Dim X As New SomeObject" meant that the
instance X was only created if it was referenced - something that went
against the general recommendations for performance reasons
(every reference to X was wrapped in code checking for the existence
of X behind the scenes, which would bloat the compiled .exe), but for
*expensive* objects, I still think a similar pattern has its uses.

Well, that's what 'WeakReference' is basically for, except that its behavior
is different in matters of object destruction.
 
H

Herfried K. Wagner [MVP]

Joergen Bech @ post1.tele.dk> said:
Like this?
---
Private m_MyValue As Integer
Public Property MyValue() As Integer
Get
Return m_MyValue
End Get
Private Set(ByVal value As Integer)
m_MyValue = value
End Set
End Property

Well, this is possible since VB 2005 and not supported by VB.NET 2002/2003.
 
C

Cor Ligthert [MVP]

Herfried,

I had to look 3 times before I saw it, you know probably what the
intelisence gives back on such a property?

Cor
 
C

Cor Ligthert [MVP]

Carlos,

Although the sample from Joergen is inviting to pass the checking in the
property rules by using the method (therefore my answer) do I use myself
forever the private members inside the class.

The main reason is that I hate it when I am debugging step by step to see
the code go up and down.

Cor
 
H

Herfried K. Wagner [MVP]

Cor Ligthert said:
I had to look 3 times before I saw it, you know probably what the
intelisence gives back on such a property?

Sorry, I cannot follow you...
 
J

Joergen Bech

Well, that's what 'WeakReference' is basically for, except that its behavior
is different in matters of object destruction.

WeakReference - as I understand it - is used for tracking the state of
a previously created object which may or may not have been garbage
collected, i.e. it can be used to figure out if an object is still
alive and can be reused or if it needs to be recreated.

I do not see where WeakReference applies to any objects that have
not been created in the first place(?)

/JB
 
C

CMM

Yeah me too!!!

Though I guess if you 1) Use Me. on Accessors and 2) camelCase on vars it's
A LOT easier to tell at a glance when you're about to step *into* an
Accessor and hit F10 to step over it. :)
 
J

Joergen Bech

Carlos,

Although the sample from Joergen is inviting to pass the checking in the
property rules by using the method (therefore my answer) do I use myself
forever the private members inside the class.

The main reason is that I hate it when I am debugging step by step to see
the code go up and down.

Cor

You can decorate your property Get/Sets with the
DebuggerStepThrough attribute to get around that, so
that in itself is not an argument for going the direct route.

Problem is, with properties, the attribute has to be
applied to the Get function and Set method individually,
rather than the whole property itself, which messes up
the indentation and makes the code less readable, i.e.:

Public Property DragForm() As Boolean
<System.Diagnostics.DebuggerStepThrough()> _
Get
Return _DragForm
End Get
<System.Diagnostics.DebuggerStepThrough()> _
Set(ByVal value As Boolean)
If _DragForm = value Then
Return
End If
_DragForm = value
End Set
End Property

Other than disabling the auto-formatting of the source, I don't
see how this problem can be solved. :(

/JB
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top