Re: Shared Method Problem With "Global" Storage



"eBob.com" <eBob.com@xxxxxxxxxxxxxxxx> schrieb
Hi Armin, Thanks for your response. Please see my further question
below interspersed with the code and your comments ...

----- Original Message -----
From: "Armin Zingler" <az.nospam@xxxxxxxxxx>
Newsgroups: microsoft.public.dotnet.languages.vb
Sent: Friday, October 19, 2007 1:19 PM
Subject: Re: Shared Method Problem With "Global" Storage


> "eBob.com" <eBob.com@xxxxxxxxxxxxxxxx> schrieb
> > I have this nasty problem with Shared methods and what I think
> > of as "global storage" - i.e. storage declared outside of any
> > subroutines or functions.
>
> It's called a "field".
>
> > In the simple example below this "global" storage is
> > ButtonHasBeenClicked. In this simple example code in Form1 calls
> > a routine in Module1 which then calls code back in Form1
> > (subroutine WhatEver). WhatEver needs to access
> > ButtonHasBeenClicked but the reference to ButtonHasBeenClicked
> > results in the error reflected in the comment. I don't see any
> > ambiguity in what I am trying to do. I suspect there is some
> > syntatic solution but I have been unable to find it.
> >
> > Thanks much for whatever solution and/or understanding you can
> > provide.
> >
> > Bob
> >
> > Public Class Form1
> > Inherits System.Windows.Forms.Form
> >
> > Dim ButtonHasBeenClicked As Boolean
>
>
> If it is not Shared, every instance of the Form has it's own value
> in this field.
>
>
> > Public Shared Sub WhatEver()
> >
> > If ButtonHasBeenClicked Then ' Cannot refer to an
> > instance member of a class from within a shared method or shared
> > member
> > initializer without an explicit instance of the class.
>
>
> In a shared Sub, you can not access an instance field withouth
> having a reference to the object. The field of which instance do
> you want to access?
> Or maybe not even one instance has been created. Therefore this
> fails. Don't
> declare the Sub as Shared.

But if I don't make WhatEver Shared then I can't call it from the
Module1 code.

Two things probably contribute to my confusion in this area. 1) In
the real project I am working on
I am using Modules simply to keep the code more manageable. The
application is mining some web sites
and I use a different Module for each site. Code which is common to
all sites is in the Form1.vb code.
And 2) apparently there can be more than one Form1, but I see Form1
as being associated with my running
application. It's the "topmost thing". It wouldn't make any sense,
for the (admitedly simple) applications I've written, to have
more than one.

What I don't get is that if I refer to ButtonHasBeenClicked in a
subroutine in the Form1.vb
code there is no question about which instance is being referenced.
But when I call (from the Form1.vb code) a subroutine
in a Module, .Net suddenly has no knowledge of what instance the
code is working on. I can
solve this problem by simply cutting and pasting the subroutine in
the Module to the Form1.vb code,
right? (But then my Form1.vb code would get unmanageably large.)

Part of my problem, I see now, is that I have misunderstood and am
misusing the Module concept. Right? But what do you do to
keep the size and organization of code files more manageable? I
need some way to segregate the code which is unique to mining web
site A from the code which is unique to mining web site B.

Sorry to be crying on your shoulder. What I know about VB.Net is
self-taught and there are major holes in my understanding.


Sorry, longer than intended:


Modules vs Classes
-------------------
Modules are Classes. The (most important) differences are:
- All members in a Module are implicitly declared Shared.
- The Module is imported at project level.

Consequently, these two versions are equal:

Version M:

Module M
Sub Test
End Sub
End Module

Version C:

Class C
Shared Sub Test
End Sub
End Class

+ "Imports C" at project level


In both cases, you can simply write "Test" anywhere in the project in order
to call Sub Test.


Shared vs instance methods
--------------------------
A: Fields

If you create an object (AKA an instance of a Class), it occupies a block of
memory. It consists of all the instance fields of the Class. More fields,
more memory. Five instances, five times the same sized block of memory.

All Shared fields in the class are there once. Always. From the start til
the end of the process. No matter how many instances exist.

-> memory consumption = 1 x shared fields + n x instance fields


B: Methods

All methods in the class are there only once. This is true for intance
methods and for Shared methods. It wouldn't make sense to have them twice or
more often because the code is always the same. It doesn't matter how many
instances exist.

The difference between shared and instance methods is:
Instance methods can access instance fields. Consequently they need a
reference to an object.
Shared methods can not access instance fields because they don't have a
reference to an object.

Internally, the difference is:
An instance method has an additional, invisible parameter called "Me". Me
points to the object for which the instance method is to be executed for. By
having this parameter, it is obvious that the method can access all the
fields inside the object referenced by "Me". In an instance method, writing
"Me." is optional, therefore writing "ButtonHasBeenClicked" is equal to
"Me.ButtonHasBeenClicked".

Because a shared method does not have this invisible "Me" parameter, it can
not refer to a certain object and therefore it can not access instance
fields. There can be 0, 1 or 1 million objects, but the shared method
wouldn't know which one to access.


Have a look at this class:

Class C
Public Value As Integer

Shared Sub Test1(ByVal TheObject As C)
TheObject.Value = 17
End Sub
Sub Test2()
Me.Value = 17
End Sub

End Class

Usage:
Dim o As New C
C.Test1(o)
o.Test2()


Both methods do the same. It's just the object-oriented language syntax that
makes us see the second call as calling a "method of the object o".


Personally I don't use modules at all, but that's personal taste. I only use
shared methods in classes. The reason is that, with classes, the members are
not auto-imported. As a consequence, I have to specify the class name to
call the method (Classname.Method). I like it more because I will always be aware of the namespace/class structure. With modules, all member names of all modules are put into a single big (unstructured) pot. Though, you can use modules if you prefer them.


If you still have implementation questions, please ask.


Armin

.


Loading