Why does this work?

G

Gagan

Hi All,

I am new to VB.NET, and am confused by following code. The code
basically obtains an instance of an object from a helper method. This
helper method instantiates a new object, and returns it. But in its
Finally block, it sets the returned object to Nothing. What perplexes
me is that caller receives a valid object instance.

The queston is: does this work because I am lucky, or this is really
an expected behavior? Also, is this a correct coding practice? Will
appreciate explanation.

Thanks!

Gagan
=============

Module Module1

Class Salary
Private m_Amount As Double = 0.0

Public Property Amount() As Double
Get
Return m_Amount
End Get
Set(ByVal value As Double)
m_Amount = value
End Set
End Property
End Class

Public Function GetSalary(ByVal dblAmount As Double) As Salary

Dim pSalary As Salary = Nothing

Try
pSalary = New Salary()
pSalary.Amount = dblAmount

Return pSalary
Catch ex As Exception
'
Finally
pSalary = Nothing
End Try

End Function


Sub Main()
Dim pSalary As Salary = GetSalary(100.0)
System.Console.WriteLine(pSalary.Amount)
End Sub

End Module
 
A

Armin Zingler

Gagan said:
Hi All,

I am new to VB.NET, and am confused by following code. The code
basically obtains an instance of an object from a helper method.
This helper method instantiates a new object, and returns it. But in
its Finally block, it sets the returned object to Nothing. What
perplexes me is that caller receives a valid object instance.

The queston is: does this work because I am lucky, or this is really
an expected behavior?

This is expected. You set the value of the local variable pSalary in the
Finally block, but when the Return statement has been executed (before), the
variable was not nothing, thus the function return value is not Nothing.
What you do to the local variable after setting the return value has no
effect on the return value.
Also, is this a correct coding practice?

Which practice? If you mean setting local variables to Nothing before the
end of the procedure, only very few people do this. I don't because it's
superfluous because the variable is running out of scope anyways.

Armin
 
G

Gagan

This is expected. You set the value of the local variable pSalary in the
Finally block, but when the Return statement has been executed (before), the
variable was not nothing, thus the function return value is not Nothing.
What you do to the local variable after setting the return value has no
effect on the return value.

Ok, I understand. The variable is local, but it points to the object
that is allocated on the heap.

I have another question: what exactly happens when the return
statement is executed? It apparently doesn't return the control to
the caller immediately. Probably it pushes the return value on the
stack, so that caller can pop it - and later changes to the local
variable doesn't affect the value on the stack. Is this correct
thinking?

Thanks for the response.

Gagan
 
C

Cor Ligthert[MVP]

Gagan,
Ok, I understand. The variable is local, but it points to the object
that is allocated on the heap.
This is absolute not what Armin wrote. Just read his message again.

Cor
 
G

Gagan

Gagan,


This is absolute not what Armin wrote. Just read his message again.

Cor

I read his message again. Can you tell me where the object is created
as a result of calling the New() ?

Thanks.

Gagan
 
D

Dave Griffiths

At the start of the Try Block

Try
pSalary = New Salary()
pSalary.Amount = dblAmount

Return pSalary
 
A

Armin Zingler

Gagan said:
Ok, I understand. The variable is local, but it points to the object
that is allocated on the heap.

You probably assume that the return value is a reference to the local
variable, but it is not. If that was the case, you were right.

What happens is, the Return statement sets the function return value. The
return value is a reference to an object. The caller gets a copy of the
reference to the object. In general, after modifying the source of a copy,
the copy remains unchanged. In your case, the local variable holding the
reference to the object is copied. Changing the local variable doesn't
affect the copy, i.e. the function return value, made before.
I have another question: what exactly happens when the return
statement is executed? It apparently doesn't return the control to
the caller immediately. Probably it pushes the return value on the
stack, so that caller can pop it - and later changes to the local
variable doesn't affect the value on the stack. Is this correct
thinking?

The return statement
1. sets the function return value
2. processes the finally sections of enclosing try-sections (this includes
using sections)
3. exits the function.

The function return value is not returned on the stack. Internally, 32-Bit
values are usually returned in a processor registers (EAX). This includes
object references (at least on a 32-Bit target plattform) that are also
32-Bit values. But that's implementation detail, so it may change in future
runtime/JIT versions. Calling conventions:
http://en.wikipedia.org/wiki/Calling_convention
http://en.wikipedia.org/wiki/X86_calling_conventions


Armin
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

Gagan said:
I read his message again. Can you tell me where the object is created
as a result of calling the New() ?

Thanks.

Gagan

On the heap. Just as you said. :)

You were absolutely correct in your analysis.

The variable is local, and it's a reference to the object that is
created on the heap. When you copy the reference into the return value,
there are two references to the same object. Changing the reference in
the local variable after the return value has been set doesn't affect
the return value and doesn't affect the object on the heap.
 
B

Bill McCarthy

Hi Gagan,

Let me try to explain form a different approach.

First in the Finally block change the pSalary = Nothing to something like
pSalary.Amount = 20
You'll see the output is 20. So the pSalary variable is pointing at the
Salary object that is returned.

Now change the code back to how you had it, setting pSalary to Nothing.
What that does is means the pSalary varaible is no longer pointing to the
object in the heap. That Object however has been assigned to functions
return value already though so changes to the pSalary variable make no
changes to what is returned, but changes to the Object itself do.

So the behaviorual equivalent of the code is :


Public Function GetSalary(ByVal dblAmount As Double) As Salary

Dim hidden_return_value_on_stack As Salary
Dim pSalary As Salary = Nothing

Try
pSalary = New Salary()
pSalary.Amount = dblAmount

hidden_return_value_on_stack = pSalary
Catch ex As Exception
'
Finally
pSalary = Nothing
End Try

' automatically returns hidden_return_value_on_stack
End Function




In VB you can actually write this using the method name, but I prefer not to
as the code can be more confusing especially is there are any overloads, eg:

Public Function GetSalary(ByVal dblAmount As Double) As Salary

Dim pSalary As Salary = Nothing

Try
pSalary = New Salary()
pSalary.Amount = dblAmount

GetSalary = pSalary
Catch ex As Exception
'
Finally
pSalary = Nothing
End Try

' automatically returns GetSalary
End Function
 
G

Gagan

Hi Gagan,

Let me try to explain form a different approach.

First in the Finally block change the pSalary = Nothing to something like
pSalary.Amount = 20
You'll see the output is 20. So the pSalary variable is pointing at the
Salary object that is returned.

Bill,

That's exactly what I had done to figure out that object was created
on heap and pSalary was just a pointer to it :) Thanks!

Gagan
 
G

Gagan

You probably assume that the return value is a reference to the local
variable, but it is not. If that was the case, you were right.
<snip>

Armin,

I found that my real reason for the confusion was my assumption that
return statement must be returning control back to the caller. And, in
my infinite wisdom, I also thought that compiler must be smart enough
to generate the code such that it would execute the finally block
before the return is executed. But that is not so, as I learnt.
Thanks!

Gagan
 
G

Gagan

Hi All,

I am new to VB.NET, and am confused by following code. The code
basically obtains an instance of an object from a helper method. This
helper method instantiates a new object, and returns it. But in its
Finally block, it sets the returned object to Nothing. What perplexes
me is that caller receives a valid object instance.

The queston is: does this work because I am lucky, or this is really
an expected behavior? Also, is this a correct coding practice? Will
appreciate explanation.

Many thanks to everyone for their responses, I really learnt something
out of this.

Gagan
 

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