-----------------------------------------------------------
New Message on BDOTNET
-----------------------------------------------------------
From: Sitaraman
Message 1 in Discussion
Hi Group In general when u want a variable to be shared at class level, you use a
static(Shared in VB.Net) variable. The words "Shared and "Static" are quite confusing
. "In VB.Net(not in C#) , you have the Shared and the Static keywords. It means that
it is possible to have a) Class Level(Member) Static variable -Using the Shared
Keyword b) Method Level(Local) Static variable(???) -Using the Static Keyword(not in
C#) Some of the articles talk about both Shared and Static being the same only that
their scope being different. But this is not quite accurate. When u declare a local
variable as Static, the behaviour is quite interesting. If the Function in
which the static variable is declared is itself NOT Shared, then the local static
variables will behave like simple Class Level Instance variables, that is they will
retain the data till the time the object goes out of scope and the data is not shared
across instances If the Function in which the static variable is declared is
itself Shared, then the local static variables will behave like Class Level Shared
Variables and the data is shared across instances. Al this might sound confusing. So
lets take a look at the example below
----------------------------------------------------------------------------------------------------------------------------------------------------------
Module Module1
Sub Main() Console.WriteLine("C L M S V V - Class Level Member Shared Variable
Value") Console.WriteLine("C L M I V V - Class Level Member Instance Variable Value")
Console.WriteLine("MLLSVV - Method Level Local Shared Variable Value")x()
y()
Console.ReadLine()
Console.WriteLine("Calling x() and y() again.Note the difference. Press Enter to See
the next set of Output" & vbCrLf)
x()
y() Console.WriteLine("Press Enter to Exit" & vbCrLf)
Console.ReadLine()
End Sub
Sub x()
Dim l_objTestClass As New TestClass()
Dim ictr As Integer Console.WriteLine("Instance 1 INSTANCE
Method(fnPrintSharedAndStaticVariableValues) Call output")
Console.WriteLine("----------------------------------------")
For ictr = 0 To 5
l_objTestClass.fnPrintSharedAndStaticVariableValues()
Next
Console.WriteLine("----------------------------------------" & vbCrLf)
Console.WriteLine("Press Enter to See the next set of Output" & vbCrLf)
Console.ReadLine() Dim l_objTestClass2 As New TestClass()
Console.WriteLine("Instance 2 INSTANCE Method(fnPrintSharedAndStaticVariableValues)
Call output")
Console.WriteLine("NOTE THAT THE CLASS LEVEL VARIABLE RETAINS VALUE AND NOT THE OTHER
TWO(CLASS LEVEL INSTANCE VARIABLE AND NORMAL METHOD LEVEL STATIC VARIABLE) ")
Console.WriteLine("----------------------------------------")
For ictr = 0 To 5
l_objTestClass2.fnPrintSharedAndStaticVariableValues()
Next
Console.WriteLine("----------------------------------------" & vbCrLf)
Console.WriteLine("Press Enter to See the next set of Output" & vbCrLf)
Console.ReadLine()
End Sub Sub y()
Dim l_objTestClass As New TestClass()
Dim ictr As Integer Console.WriteLine("Instance 1 SHARED
Method(fnSHAREDPrintSharedAndStaticVariableValues2) Call output")
Console.WriteLine("----------------------------------------")
For ictr = 0 To 5
l_objTestClass.fnSHAREDPrintSharedAndStaticVariableValues2()
Next
Console.WriteLine("----------------------------------------" & vbCrLf)
Console.WriteLine("Press Enter to See the next set of Output" & vbCrLf)
Console.ReadLine() Dim l_objTestClass2 As New TestClass()
Console.WriteLine("Instance 2 SHARED
Method(fnSHAREDPrintSharedAndStaticVariableValues2) Call output")
Console.WriteLine("NOTE THAT BOTH THE CLASS LEVEL VARIABLE AND SHARED NORMAL LEVEL
STATIC VARIABLE RETAIN VALUE ) ")
Console.WriteLine("----------------------------------------")
For ictr = 0 To 5
l_objTestClass2.fnSHAREDPrintSharedAndStaticVariableValues2()
Next
Console.WriteLine("----------------------------------------" & vbCrLf)
End Sub
End Module
Public Class TestClass 'Declare a Class Level(Member) Shared Variable
Shared m_intSharedVariable1 As Integer = 0 'Declare a Class Level Member Instance
Variable
Private m_intVariable1 As Integer = 0 Public Function
fnPrintSharedAndStaticVariableValues()
'Declare a Method Level(Local) Static Variable
Static l_intStaticVariable1 As Integer = 0 'Increment the Class Level(Member)
Shared Variable
m_intSharedVariable1 = m_intSharedVariable1 + 1 'Increment the Class Level Member
Instance Variable
m_intVariable1 = m_intVariable1 + 1 'Increment the Method Level(Local) Static Variable
l_intStaticVariable1 = l_intStaticVariable1 + 1 'Print the value of the Class
Level(Member) Shared Variable
Console.WriteLine("C L M S V V: " & m_intSharedVariable1) 'Print the value of the
Class Level(Member) Instance Variable
Console.WriteLine("C L M I V V: " & m_intVariable1)
'Print the value of the Method Level(Local) Static Variable
Console.WriteLine("M L L S V V : " & l_intStaticVariable1)
End Function
Public Shared Function fnSHAREDPrintSharedAndStaticVariableValues2()
'Declare a Method Level(Local) Static Variable
Static l_intStaticVariable1 As Integer = 0 'Increment the Class Level(Member) Shared
Variable
m_intSharedVariable1 = m_intSharedVariable1 + 1 'Increment the Method Level(Local)
Static Variable
l_intStaticVariable1 = l_intStaticVariable1 + 1 'Print the value of the Class
Level(Member) Shared Variable
Console.WriteLine("C L M S V V: " & m_intSharedVariable1) 'Print the value of the
Method Level(Local) Static Variable
Console.WriteLine("M L L S V V : " & l_intStaticVariable1)
End Function
End Class
----------------------------------------------------------------------------------------------------------------------------------------------------------
The output of this would be ---------------------------------------- C L M S V V -
Class Level Member Shared Variable Value C L M I V V - Class Level Member Instance
Variable Value MLLSVV - Method Level Local Shared Variable Value Instance 1 INSTANCE
Method(fnPrintSharedAndStaticVariableValues) Call output
----------------------------------------
C L M S V V : 1
C L M I V V: 1
M L L S V V : 1
C L M S V V : 2
C L M I V V : 2
M L L S V V : 2
C L M S V V : 3
C L M I V V : 3
M L L S V V : 3
C L M S V V : 4
C L M I V V : 4
M L L S V V : 4
C L M S V V : 5
C L M I V V : 5
M L L S V V : 5
C L M S V V : 6
C L M I V V : 6
M L L S V V : 6
---------------------------------------- Press Enter to See the next set of Output
Instance 2 INSTANCE Method(fnPrintSharedAndStaticVariableValues) Call output
NOTE THAT THE CLASS LEVEL VARIABLE RETAINS VALUE AND NOT THE OTHER TWO(CLASS LEVEL
INSTANCE VARIABLE AND NORMAL METHOD LEVEL STA
TIC VARIABLE)
----------------------------------------
C L M S V V : 7
C L M I V V : 1
M L L S V V : 1
C L M S V V : 8
C L M I V V : 2
M L L S V V : 2
C L M S V V : 9
C L M I V V : 3
M L L S V V : 3
C L M S V V : 10
C L M I V V : 4
M L L S V V : 4
C L M S V V : 11
C L M I V V: 5
M L L S V V : 5
C L M S V V : 12
C L M I V V : 6
M L L S V V : 6
---------------------------------------- Press Enter to See the next set of Output
Instance 1 SHARED Method(fnSHAREDPrintSharedAndStaticVariableValues2) Call output
----------------------------------------
C L M S V V : 13
M L L S V V : 1
C L M S V V : 14
M L L S V V : 2
C L M S V V : 15
M L L S V V : 3
C L M S V V : 16
M L L S V V : 4
C L M S V V : 17
M L L S V V : 5
C L M S V V : 18
M L L S V V : 6
---------------------------------------- Press Enter to See the next set of Output
Instance 2 SHARED Method(fnSHAREDPrintSharedAndStaticVariableValues2) Call output
NOTE THAT BOTH THE CLASS LEVEL VARIABLE AND SHARED NORMAL LEVEL STATIC VARIABLE RETAIN
VALUE )
----------------------------------------
C L M S V V : 19
M L L S V V : 7
C L M S V V : 20
M L L S V V : 8
C L M S V V : 21
M L L S V V : 9
C L M S V V : 22
M L L S V V : 10
C L M S V V : 23
M L L S V V : 11
C L M S V V : 24
M L L S V V : 12
----------------------------------------
Calling x() and y() again.Note the difference. Press Enter to See the next set of
Output Instance 1 INSTANCE Method(fnPrintSharedAndStaticVariableValues) Call output
----------------------------------------
C L M S V V : 25
C L M I V V : 1
M L L S V V : 1
C L M S V V : 26
C L M I V V: 2
M L L S V V : 2
C L M S V V : 27
C L M I V V: 3
M L L S V V : 3
C L M S V V : 28
C L M I V V: 4
M L L S V V : 4
C L M S V V : 29
C L M I V V: 5
M L L S V V : 5
C L M S V V : 30
C L M I V V: 6
M L L S V V : 6
---------------------------------------- Press Enter to See the next set of Output
Instance 2 INSTANCE Method(fnPrintSharedAndStaticVariableValues) Call output
NOTE THAT THE CLASS LEVEL VARIABLE RETAINS VALUE AND NOT THE OTHER TWO(CLASS LEVEL
INSTANCE VARIABLE AND NORMAL METHOD LEVEL STA
TIC VARIABLE)
----------------------------------------
C L M S V V : 31
C L M I V V : 1
M L L S V V : 1
C L M S V V : 32
C L M I V V: 2
M L L S V V : 2
C L M S V V : 33
C L M I V V: 3
M L L S V V : 3
C L M S V V : 34
C L M I V V: 4
M L L S V V : 4
C L M S V V : 35
C L M I V V: 5
M L L S V V : 5
C L M S V V : 36
C L M I V V: 6
M L L S V V : 6
---------------------------------------- Press Enter to See the next set of Output
Instance 1 SHARED Method(fnSHAREDPrintSharedAndStaticVariableValues2) Call output
----------------------------------------
C L M S V V : 37
M L L S V V : 13
C L M S V V : 38
M L L S V V : 14
C L M S V V : 39
M L L S V V : 15
C L M S V V : 40
M L L S V V : 16
C L M S V V : 41
M L L S V V : 17
C L M S V V : 42
M L L S V V : 18
---------------------------------------- Press Enter to See the next set of Output
Instance 2 SHARED Method(fnSHAREDPrintSharedAndStaticVariableValues2) Call output
NOTE THAT BOTH THE CLASS LEVEL VARIABLE AND SHARED NORMAL LEVEL STATIC VARIABLE RETAIN
VALUE )
----------------------------------------
C L M S V V : 43
M L L S V V : 19
C L M S V V : 44
M L L S V V : 20
C L M S V V : 45
M L L S V V : 21
C L M S V V : 46
M L L S V V : 22
C L M S V V : 47
M L L S V V : 23
C L M S V V : 48
M L L S V V : 24
---------------------------------------- Press Enter to Exit
---------------------------------------- The output shows that the Method
Level(Local) Static Variables behave differently when declared in a instance method
and a Shared method. The Method level Static Variable l_intStaticVariable1
behaves just like the Class Level Instance Variable m_intVariable1, because it is
defined in a instance method fnPrintSharedAndStaticVariableValues. The Method
level Static Variable l_intStaticVariable2 behaves just like the Class Level Shared
Variable m_m_intSharedVariable1, because it is defined in a Shared method
fnSHAREDPrintSharedAndStaticVariableValues2 How is this possible. How exactly are
Method Level Static Variables handled. Are they instance based or static. How is the
data persisted even though they are declared inside a method. There is no magic in
it and an answer all this is the is the juggling that the vbc compiler performs to
achieve this dynamism at the time of compiling the Source Code to IL Lets see how it
actually happened in 2 steps below 1) IL Level : The Source Code is compiled to IL.
Right!!! Lets use the ILDASM on the compiled code to see how the Disassembly looks
like Test Class
$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1:private
specialname int32
$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1$Init : private
specialname class
$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$2001C$l_intStaticVariable2:private
static specialname int32
$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$2001C$l_intStaticVariable2$Init :
private static specialname class
[Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StaticLocalInitFlag
m_intSharedVariable1 : private static int32 method public instance object
fnPrintSharedAndStaticVariableValues() cil managed method public static object
fnSHAREDPrintSharedAndStaticVariableValues2() cil managed If u look at the TestClass
Source Code we had one variable m_intSharedVariable1, which was Shared and one
function fnPrintSharedAndStaticVariableValues. However on compilation the VB Compiler
has done some extra tasks for free. it has made the Shared Keyword as
static(which is cool and is consistent with C# semantics also and is irrelevant for us
now)
Moved(Copied to be precise) the Method Level(Local) Variable
l_intStaticVariable1 to a Class Level Member(instance) variable and assigned it a
unique variable name,
$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1.Note that it
is a combination of the the Name of the "Method Level Static Variable" + The Name of
the Method in which this variable was declared + Special Characters.Also note that the
newly created Class Level variable is an instance variable coz, the function in which
the static variable was defined was an instance
method(fnPrintSharedAndStaticVariableValues)
Added one more Variable
$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1$Init of type
Microsoft.VisualBasic.CompilerServices.StaticLocalInitFlag (This is a interesting
namespace, has a wonderful set of utility functions, more on it later). This is an
instance variable for the reason as mentioned in point 2
Moved(Copied to be precise) the Method Level(Local) Variable
l_intStaticVariable2 to a Class Level Member(static) variable and assigned it a unique
variable name,
$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$2001C$l_intStaticVariable2.Note
that it is a combination of the the Name of the "Method Level Static Variable" + The
Name of the Method in which this variable was declared + Special Characters. Also note
that the newly created Class Level variable is an static variable coz, the function in
which the static variable was defined was a Shared
method(fnSHAREDPrintSharedAndStaticVariableValues2)
Added one more Variable
$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$2001C$l_intStaticVariable2$Init of
type Microsoft.VisualBasic.CompilerServices.StaticLocalInitFlag . This is Shared
variable for the reason as mentioned in point 4
So from this wat we can guess is that, when u create a local static variable, on
compilation the compiler creates a class level instance variable and also creates a
flag. So whenever this variable is accessed for the first time, the variable will be
initialized with the value and after tht it will always hold the value across method
calls just as any static variable. But how to be sure that we are correct. Ill use the
Reflector tool( the download link for which i had posted some time ago) to DECOMPILE
the exe and look at the function 2) DeCompiled Code Level : When you decompile the
code using the Reflector tool( u can download it from
http://www.aisto.com/roeder/dotnet/, SDK also available), the decompiled source code
is as follows Public Class TestClass Inherits Object Private
$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1 As Integer
Private $STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1$Init
As StaticLocalInitFlag
Private Shared
$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$001C$l_intStaticVariable2 As
Integer
Private Shared
$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$001C$l_intStaticVariable2$Init As
StaticLocalInitFlag
Private Shared m_intSharedVariable1 As Integer
Private m_intVariable1 As Integer Private Shared Sub New()
Begin Sub
TestClass.m_intSharedVariable1 = 0
TestClass.$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$001C$l_intStaticVariable2$Init
= New StaticLocalInitFlag
End Sub Public Sub New()
Begin Sub
MyBase..ctor
Me.m_intVariable1 = 0
Me.$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1$Init = New
StaticLocalInitFlag
End Sub Public Function fnPrintSharedAndStaticVariableValues() As Object
Begin Function
Dim obj1 As Object
If
(Me.$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1$Init.State
= 1) Then
goto L_0071
End If
Monitor.Enter(Me.$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1$Init)
If
(Me.$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1$Init.State
= 0) Then
Me.$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1$Init.State
= 2
Me.$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1 = 0
Else
If
(Me.$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1$Init.State
= 2) Then
Throw New IncompleteInitialization
End If
End If
goto L_0070
Me.$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1$Init.State
= 1
Monitor.Exit(Me.$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1$Init)
L_0070:
TestClass.m_intSharedVariable1 = (TestClass.m_intSharedVariable1 + 1)
Me.m_intVariable1 = (Me.m_intVariable1 + 1)
Me.$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1 =
(Me.$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1 + 1)
Console.WriteLine(String.Concat("C L M S V V : ",
StringType.FromInteger(TestClass.m_intSharedVariable1)))
Console.WriteLine(String.Concat("Class Level(Member) Variable Value : ",
StringType.FromInteger(Me.m_intVariable1)))
Console.WriteLine(String.Concat("M L L S V V : ",
StringType.FromInteger(Me.$STATIC$fnPrintSharedAndStaticVariableValues$2001C$l_intStaticVariable1)))
Return obj1
End Function
Public Shared Function fnSHAREDPrintSharedAndStaticVariableValues2() As Object
Begin Function
Dim obj1 As Object
If
(TestClass.$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$001C$l_intStaticVariable2$Init.State
= 1) Then
goto L_0069
End If
Monitor.Enter(TestClass.$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$001C$l_intStaticVariable2$Init)
If
(TestClass.$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$001C$l_intStaticVariable2$Init.State
= 0) Then
TestClass.$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$001C$l_intStaticVariable2$Init.State
= 2
TestClass.$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$001C$l_intStaticVariable2
= 0
Else
If
(TestClass.$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$001C$l_intStaticVariable2$Init.State
= 2) Then
Throw New IncompleteInitialization
End If
End If
goto L_0068
TestClass.$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$001C$l_intStaticVariable2$Init.State
= 1
Monitor.Exit(TestClass.$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$001C$l_intStaticVariable2$Init)
L_0068:
TestClass.m_intSharedVariable1 = (TestClass.m_intSharedVariable1 + 1)
TestClass.$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$001C$l_intStaticVariable2
=
(TestClass.$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$001C$l_intStaticVariable2
+ 1)
Console.WriteLine(String.Concat("C L M S V V : ",
StringType.FromInteger(TestClass.m_intSharedVariable1)))
Console.WriteLine(String.Concat("M L L S V V : ",
StringType.FromInteger(TestClass.$STATIC$fnSHAREDPrintSharedAndStaticVariableValues2$001C$l_intStaticVariable2)))
Return obj1
End Function
End Class Here note that both the functions are almost the same. Basically wat
the compiler has done is to add some plumbing code(Adding Class Level Variable Flag
Checking, Initialization of Flag etc) and modify existing code(the local variable that
u declared has been removed by the compiler and some inlining has been done) to ensure
that the Method level Static Variable is managed To Conclude A Static(Method
Level) Variable is does not automatically translate to a Shared(Class Level) Variable
Only similarity is that it is capable of retaining the data even after the method
call is over, which is possible even in an instance variable A Method Level
Static Variable Declared in a method can become either a Class Level Instance Variable
or a Class Level Shared Variable If the variable's declaring method is a
Shared method then the compiler will create an equivalent Class Level Shared Variable
for the Method Level Static Variable If the variable's declaring method is a
Instance method then the compiler will create an equivalent Class Level Instance
Variable for the Method Level Static Variable All the juggling and plumbing
code is written by the compiler to check for initialization etc.
Hope this helps
Im attaching the sample solution of the example given above. The ILDASM tool can be
loaded from the VS.Net Command Prompt by typing ILDASM.exe <EXE/DLL FileName>. The
Reflector tool can be downloaded from http://www.aisto.com/roeder/dotnet/ .
Hope this helps
regards, sr p.s. The MSDN does not provide much help on the CompilerServices
Namespace. Even intellisense does not show me the classes. So i opened the
Microsoft.VisualBasic
Assembly(file:///c:/winnt/assembly/gac/microsoft.visualbasic/7.0.3300.0__b03f5f7f11d50a3a/microsoft.visualbasic.dll
on my machine which runs .Net1.0 FW ) in the Reflector tool and checked the
CompilerServices Namespace classes. There are quite a few useful methods available
here which will help u understand how exactly are things manipulated at compiletime.
Check it out.....
-----------------------------------------------------------
To stop getting this e-mail, or change how often it arrives, go to your E-mail
Settings.
http://groups.msn.com/BDotNet/_emailsettings.msnw
Need help? If you've forgotten your password, please go to Passport Member Services.
http://groups.msn.com/_passportredir.msnw?ppmprop=help
For other questions or feedback, go to our Contact Us page.
http://groups.msn.com/contact
If you do not want to receive future e-mail from this MSN group, or if you received
this message by mistake, please click the "Remove" link below. On the pre-addressed
e-mail message that opens, simply click "Send". Your e-mail address will be deleted
from this group's mailing list.
mailto:[EMAIL PROTECTED]