How come I can call Public Methods of a Form as if they were Shared?
-
Today at work a co-worker had a problem. Everywhere in the code
Methods
of aForm
were called, but we could not find any instance of the Form. I was shocked to find out that aPublic Class Form1
could be used as though all itsPublic Methods
wereShared
(and none actually was!)... Example:Public Class Form1
Public Sub DoSomething()
End SubEnd Class
Public Class Class1
Public Sub DoSomethingElse()
Form1.Width = 1000
Form1.DoSomething()
Form1.Text = "Hello"
Form1.Button1.Text = "Me too..."
Form1.Show
End SubEnd Class
That bit of code is totally legit in VB, even with option Strict on! Is nothing sacred anymore? :confused: What is also weird is that when I tried to do this at work I could not reproduce it, but now I am at home at my own computer I am able to do this. Is it a setting somewhere? I also tried it in C#, but I could not call any
Public Methods
like that. Any ideas what this might be and whyForm
s in VB work like that? :confused:It's an OO world.
-
Today at work a co-worker had a problem. Everywhere in the code
Methods
of aForm
were called, but we could not find any instance of the Form. I was shocked to find out that aPublic Class Form1
could be used as though all itsPublic Methods
wereShared
(and none actually was!)... Example:Public Class Form1
Public Sub DoSomething()
End SubEnd Class
Public Class Class1
Public Sub DoSomethingElse()
Form1.Width = 1000
Form1.DoSomething()
Form1.Text = "Hello"
Form1.Button1.Text = "Me too..."
Form1.Show
End SubEnd Class
That bit of code is totally legit in VB, even with option Strict on! Is nothing sacred anymore? :confused: What is also weird is that when I tried to do this at work I could not reproduce it, but now I am at home at my own computer I am able to do this. Is it a setting somewhere? I also tried it in C#, but I could not call any
Public Methods
like that. Any ideas what this might be and whyForm
s in VB work like that? :confused:It's an OO world.
If this is about VB6 or older, I couldn't care less, as VB6 has been dead and buried for years now. In VB.NET, your code does not compile. You would need "Form1 implements Form", and then all methods/properties in DoSomethingElse() generate compile errors. :)
Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
-
If this is about VB6 or older, I couldn't care less, as VB6 has been dead and buried for years now. In VB.NET, your code does not compile. You would need "Form1 implements Form", and then all methods/properties in DoSomethingElse() generate compile errors. :)
Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
Luc Pattyn wrote:
If this is about VB6 or older
Nope, the code example I showed was VB.NET, Framework 4.0.
Luc Pattyn wrote:
In VB.NET, your code does not compile.
It compiles, runs great and works as expected (the Form is called with its Width set, the Buttons Text set etc.). I just can't get over the fact that it goes against everything I have learned about encapsulation and that .NET is right there supporting it.
Luc Pattyn wrote:
You would need "Form1 implements Form", and then all methods/properties in DoSomethingElse() generate compile errors.
It gets worse....
Public Class Form1
Private Sub Form1\_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Form2.Something() Form2.Button1.Text = "Hello" Form2.Show() End Sub Private Sub Button1\_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Form1.Show() End Sub
End Class
Public Class Form2
Public Sub Something() Me.Text = "Test" Me.NothingIsSacredAnymore() End Sub Private Sub NothingIsSacredAnymore() MessageBox.Show("Hello") End Sub
End Class
I am starting Form1, which immediatly calls Form2.Something, without first instantiating it. Form2.Something calls a Private Sub and everything is ok. I can't call NothingIsSacredAnymore directly from Form1 though. When I start the application I first get the MessageBox saying "Hello", then Form1 and Form2 show and Form2 has it's text set to "Test" and its Buttons Text set to "Hello". When I click the Button1 on Form1 nothing happens if Form2 is already open. If it is not it opens Form2, but with default property settings.
It's an OO world.
-
Today at work a co-worker had a problem. Everywhere in the code
Methods
of aForm
were called, but we could not find any instance of the Form. I was shocked to find out that aPublic Class Form1
could be used as though all itsPublic Methods
wereShared
(and none actually was!)... Example:Public Class Form1
Public Sub DoSomething()
End SubEnd Class
Public Class Class1
Public Sub DoSomethingElse()
Form1.Width = 1000
Form1.DoSomething()
Form1.Text = "Hello"
Form1.Button1.Text = "Me too..."
Form1.Show
End SubEnd Class
That bit of code is totally legit in VB, even with option Strict on! Is nothing sacred anymore? :confused: What is also weird is that when I tried to do this at work I could not reproduce it, but now I am at home at my own computer I am able to do this. Is it a setting somewhere? I also tried it in C#, but I could not call any
Public Methods
like that. Any ideas what this might be and whyForm
s in VB work like that? :confused:It's an OO world.
-
Luc Pattyn wrote:
If this is about VB6 or older
Nope, the code example I showed was VB.NET, Framework 4.0.
Luc Pattyn wrote:
In VB.NET, your code does not compile.
It compiles, runs great and works as expected (the Form is called with its Width set, the Buttons Text set etc.). I just can't get over the fact that it goes against everything I have learned about encapsulation and that .NET is right there supporting it.
Luc Pattyn wrote:
You would need "Form1 implements Form", and then all methods/properties in DoSomethingElse() generate compile errors.
It gets worse....
Public Class Form1
Private Sub Form1\_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Form2.Something() Form2.Button1.Text = "Hello" Form2.Show() End Sub Private Sub Button1\_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Form1.Show() End Sub
End Class
Public Class Form2
Public Sub Something() Me.Text = "Test" Me.NothingIsSacredAnymore() End Sub Private Sub NothingIsSacredAnymore() MessageBox.Show("Hello") End Sub
End Class
I am starting Form1, which immediatly calls Form2.Something, without first instantiating it. Form2.Something calls a Private Sub and everything is ok. I can't call NothingIsSacredAnymore directly from Form1 though. When I start the application I first get the MessageBox saying "Hello", then Form1 and Form2 show and Form2 has it's text set to "Test" and its Buttons Text set to "Hello". When I click the Button1 on Form1 nothing happens if Form2 is already open. If it is not it opens Form2, but with default property settings.
It's an OO world.
That's because, in order to make it easier to maintain some level of backwards compatibility with VB6 when converting projects from VB6 code to VB.NET, there is a little hidden collection of instances of all your Form classes in your app. If you look under My.Forms you'll find it. I hate it. There's no way to completely get rid of it and doing so is a bad idea because it's also tied in with other Application Framework functionality.
A guide to posting questions on CodeProject[^]
Dave Kreskowiak -
Also works on older versions of VB.NET. There's a thread on StackOverflow[^] on the subject :)
I are Troll :suss:
StackOverflower wrote:
VB6 programmers had a hard time with seeing the difference between a type and a reference to an object of that type. Form1 vs frm in your snippet. There's history for that, VB didn't get classes until VB4 while forms go all the way back to VB1. This is otherwise quite crippling to the programmer's mind
I spent about 30 minutes looking for some global variable today with no luck... Encapsulation is one of the most important aspects of Object Oriented Programming and Microsoft decides to NOT use it for Forms. I ask you, what is more crippling to the programmer's mind? X| This sort of stuff leads to very unexpected behaviour in software... Microsoft should have dropped it in VB4 :~
It's an OO world.
-
That's because, in order to make it easier to maintain some level of backwards compatibility with VB6 when converting projects from VB6 code to VB.NET, there is a little hidden collection of instances of all your Form classes in your app. If you look under My.Forms you'll find it. I hate it. There's no way to completely get rid of it and doing so is a bad idea because it's also tied in with other Application Framework functionality.
A guide to posting questions on CodeProject[^]
Dave KreskowiakYet another reason to use C#. Microsoft ignoring my encapsulation is a bitch... :(
It's an OO world.
-
StackOverflower wrote:
VB6 programmers had a hard time with seeing the difference between a type and a reference to an object of that type. Form1 vs frm in your snippet. There's history for that, VB didn't get classes until VB4 while forms go all the way back to VB1. This is otherwise quite crippling to the programmer's mind
I spent about 30 minutes looking for some global variable today with no luck... Encapsulation is one of the most important aspects of Object Oriented Programming and Microsoft decides to NOT use it for Forms. I ask you, what is more crippling to the programmer's mind? X| This sort of stuff leads to very unexpected behaviour in software... Microsoft should have dropped it in VB4 :~
It's an OO world.
Naerling wrote:
and Microsoft decides to NOT use it for Forms
After having read the reasoning on that thread, I can see why. Can't say I like it, just that I can see the reasoning. Just for fun, how about assigning null to a valuetype?
Naerling wrote:
Microsoft should have dropped it in VB4
Yes, I'm glad too that Microsoft introduced C# :)
I are Troll :suss:
-
That's because, in order to make it easier to maintain some level of backwards compatibility with VB6 when converting projects from VB6 code to VB.NET, there is a little hidden collection of instances of all your Form classes in your app. If you look under My.Forms you'll find it. I hate it. There's no way to completely get rid of it and doing so is a bad idea because it's also tied in with other Application Framework functionality.
A guide to posting questions on CodeProject[^]
Dave KreskowiakWaw. Who would come up with "free forms"! I had pasted the OP's code into an existing VB.NET project, and wasn't surprised it didn't compile at all, so I did not understand what the OP was on about... :thumbsup:
Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
-
StackOverflower wrote:
VB6 programmers had a hard time with seeing the difference between a type and a reference to an object of that type. Form1 vs frm in your snippet. There's history for that, VB didn't get classes until VB4 while forms go all the way back to VB1. This is otherwise quite crippling to the programmer's mind
I spent about 30 minutes looking for some global variable today with no luck... Encapsulation is one of the most important aspects of Object Oriented Programming and Microsoft decides to NOT use it for Forms. I ask you, what is more crippling to the programmer's mind? X| This sort of stuff leads to very unexpected behaviour in software... Microsoft should have dropped it in VB4 :~
It's an OO world.
In what way is encapsulation broken? The only problem I can see with this is that if you wanted your constructor to be private then this would ruin it for you. Other than that, normal class access rules still apply. VB.NET just acts like you declared
Dim Form1 As New Form1
. So the first call to a non-shared member of Form1 causes a new instance of Form1 to be created. But then, you wouldn't normally be calling non-shared members on the class anyway, so all in all the problem is fairly limited (that is to say: if you wrote your code without knowing this quirk, you wouldn't ever find out about it, because you wouldn't be directly accessing members through Form1 but via an instance). That is not to say that I at all agree with this. I hated this quirk in VB6 already, as it was more confusing than anything. Completely unintuitive and destructive to the idea of classes and OOP for new programmers if they see this behaviour -
Today at work a co-worker had a problem. Everywhere in the code
Methods
of aForm
were called, but we could not find any instance of the Form. I was shocked to find out that aPublic Class Form1
could be used as though all itsPublic Methods
wereShared
(and none actually was!)... Example:Public Class Form1
Public Sub DoSomething()
End SubEnd Class
Public Class Class1
Public Sub DoSomethingElse()
Form1.Width = 1000
Form1.DoSomething()
Form1.Text = "Hello"
Form1.Button1.Text = "Me too..."
Form1.Show
End SubEnd Class
That bit of code is totally legit in VB, even with option Strict on! Is nothing sacred anymore? :confused: What is also weird is that when I tried to do this at work I could not reproduce it, but now I am at home at my own computer I am able to do this. Is it a setting somewhere? I also tried it in C#, but I could not call any
Public Methods
like that. Any ideas what this might be and whyForm
s in VB work like that? :confused:It's an OO world.
-
How is ignoring encapsulation sounding good? :~
It's an OO world.