How does VB.NET execute a non-shared method without an instance? [duplicate] - vb.net

I'm just curious to know that there is the (Name) property, which represents the name of the Form class. This property is used within the namespace to uniquely identify the class that the Form is an instance of and, in the case of Visual Basic, is used to access the default instance of the form.
Now where this Default Instance come from, why can't C# have a equivalent method to this.
Also for example to show a form in C# we do something like this:
// Only method
Form1 frm = new Form1();
frm.Show();
But in VB.Net we have both ways to do it:
' First common method
Form1.Show()
' Second method
Dim frm As New Form1()
frm.Show()
My question comes from this first method. What is this Form1, is it an instance of Form1 or the Form1 class itself? Now as I mentioned above the Form name is the Default instance in VB.Net. But we also know that Form1 is a class defined in Designer so how can the names be same for both the Instance and class name?
If Form1 is a class then there is no (Static\Shared) method named Show().
So where does this method come from?
What difference they have in the generated IL?
And finally why can't C# have an equivalent of this?

This was added back to the language in the version of VB.NET that came with VS2005. By popular demand, 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, understanding that difference is very important to get a shot at writing effective object oriented code. A big part of the reason that C# doesn't have this.
You can get this back in C# as well, albeit that it won't be quite so clean because C# doesn't allow adding properties and methods to the global namespace like VB.NET does. You can add a bit of glue to your form code, like this:
public partial class Form2 : Form {
[ThreadStatic] private static Form2 instance;
public Form2() {
InitializeComponent();
instance = this;
}
public static Form2 Instance {
get {
if (instance == null) {
instance = new Form2();
instance.FormClosed += delegate { instance = null; };
}
return instance;
}
}
}
You can now use Form2.Instance in your code, just like you could use Form2 in VB.NET. The code in the if statement of the property getter should be moved into its own private method to make it efficient, I left it this way for clarity.
Incidentally, the [ThreadStatic] attribute in that snippet is what has made many VB.NET programmers give up threading in utter despair. A problem when the abstraction is leaky. You are really better off not doing this at all.

VB is adding a load of code into your project behind your back, basically.
The easiest way to see what's going on is to build a minimal project and look at it with Reflector. I've just created a new WinForms app with VB and added this class:
Public Class OtherClass
Public Sub Foo()
Form1.Show()
End Sub
End Class
The compiled code for Foo looks like this when decompiled as C#:
public void Foo()
{
MyProject.Forms.Form1.Show();
}
MyProject.Forms is a property in the generated MyProject class, of type MyForms. When you start diving into this you see quite large amounts of generated code in there.
C# could do all of this, of course - but it doesn't typically have a history of doing quite as much behind your back. It builds extra methods and types for things like anonymous types, iterator blocks, lambda expressions etc - but not in quite the same way that VB does here. All the code that C# builds corresponds to source code that you've written - just cleverly transformed.
There are arguments for both approaches, of course. Personally I prefer the C# approach, but that's probably no surprise. I don't see why there should be a way of accessing an instance of a form as if it was a singleton but only for forms... I like the language to work the same way whether I'm using GUI classes or anything else, basically.

Related

Member of a .NET class is empty in the VB6 object browser

At the moment I´m trying tests on the interoperability of VB6 and .NET using COM.
I have followed this simple example to call a .NET component from COM.
https://msdn.microsoft.com/en-us/library/ms973802.aspx
The DLL is registered and the assembly was "succesfully added to the cache". However when I take a look into the object browser of VB6 I can only see methods of the interface and not of the actual class. COM is set on visible and the correct path for the KeyFile, are both in the AssemblyInfo.vb file. The .NET Class+Interface looks like this:
Public Interface iTemperature
'some properties and functions
End Interface
Public Class NET_Temperature
Implements iTemperature
'some implemented public properties and functions
End Class
When I try to run the following Code:
Set moTempClass = New PhysServer2.NET_Temperature
Set moTemp = moTempClass
I´m getting the well known 429-runtime error, saying that creating an object through an Active-X-component does not work. There is a lot of information on the internet regarding this error with unregistered DLL/TLB, but I´m more concerned about the fact that only the methods and properties of the interface are shown in the object browser and not the implemented methods/properties of the interface - the class. How can I fix this Error and make the methods in my class sort of visible to COM and the object browser?

Instantiate many classes

In my current project, a circuit drawing program, I'm deriving many classes from the same base class.
Public MustInherit Class clsCompo
Public Class clsRelay Inherits clsCompo
Public Class clsResistor Inherits clsCompo
Each child class has a 'getIcon' function that provides the desired image of the component. These get loaded in a listview to be used in the drawing program.
Is there an easy way to instantiated these classes to be used? Is there another way than manually instantiating each class? And then adding the image to the listview: something like:
Dim classes() As String = {"clsResistor", "clsRelay"}
Dim c(1) As Object
For Each cls As String In classes
c(1) = New cls
'add image to listview
Next
I'm using .NET 3.5
Thanks
If your classes have a parameterless constructor:
c(1) = Activator.CreateInstance(Type.GetType("MyNamespace." & cls))
Obviously, MyNamespace. should be replaced as appropriate.
You will need to use reflection and Activator.CreateInstance specifically to perform this trick. Going towards reflection path is dangerous, and usually brings more trouble than it gives benefits. In most cases there is a better way to design your application.
In your particular case, you could have a dictionary of icons, string to icon match, then just have a constructor of clsCompo specify the icon you want as a parameter. Unless you are using inheritance for something else, this should totally solve your problem, without the burden of using reflection.

Why does adding 2nd level subclassed Button controls to a Grid give E_INVALIDARG?

I've come across the this problem dealing with subclasses of the Windows.UI.Xaml.Button class in C++/CX, and I'd like to know what's going on.
If I add a control instance to a grid, everything works as expected.
If I subclass the control and add an instance of the subclass, everything works as expected.
But if I subclass my subclassed control and add an instance of it to the grid I get E_INVALIDARG thrown during Grid::Children::Append(). What gives?
My code looks roughly like this (LayoutRoot is a Grid in MainPage.xaml, this sample has been tested in an empty simple metro application):
// Scenario 1: This works (duh!)
LayoutRoot->Children->Append(ref new Button());
// Scenario 2: This works
LayoutRoot->Children->Append(ref new MyButton1());
// Scenario 3: This doesn't work, it will cause an E_INVALIDARG to be thrown by the collection
LayoutRoot->Children->Append(ref new MyButton2());
// This is how MyButton1 and MyButton2 is defined
public ref class MyButton1 : public Button {
public:
MyButton1() {};
~MyButton1() {};
};
public ref class MyButton2 : public MyButton1 {
public:
MyButton2() {};
~MyButton2() {};
};
Note that this question is slightly similar to this question, but the error and the scenario is sufficiently different for me to post this one separately.
UPDATE: I think I'm on the right track understanding this problem after reading this article by Ian Griffiths, but I need to know more regarding the behavior of this specific example. Full code to repeat this problem can be found here, see the 3rd post in the thread.
UPDATE: From what I've learned so far, not all WinRT types support inheritance. I have no reliable source references for this, but I've read that the Windows.UI.Xaml classes should support inheritance, but other WinRT types won't. The Windows.UI.Xaml.Controls.Button class obviously does, while my own MyButton1 doesn't. I'd like to know what I'd have to do to make MyButton1 'inheritable' the way the Button class is.
I've found that replacing the Windows.UI.Xaml.Controls.Button class with Windows.UI.Xaml.Controls.ProgressBar will make scenario 2 fail, which tells me that the ProgressBar class isn't (yet) possible to subclass. This observation is what makes me believe that a class need to do something explicit in order for it to be inheritable.

Silverlight VB AddHandler to dynamic object

We are migrating an application from C# to VB to meet our project's needs but stumbled upon a problem with event handling in VB.
The application uses a COM Wrapper access a scanner in Silverlight. The object is created dynamically in the code, and an event is added to "AcquirePage". This requires elevated trust of course.
Code in C#:
dynamic TwainSession;
(...)
TwainSession.AcquirePage += new AcquirePageDelegate(AcquirePageEventHandler);
As the only real "equivalent" of dynamic in VB is Object, we use:
Private TwainSession As Object
Everything is fine up to the point we want to handle an event of this Object. Because we are in Silverlight, we cannot have knowledge of the Object's structure or events, hence the need to create it dynamically. In C# we simply use "+=" to add a handler to an event but:
AddHandler TwainSession.AcquirePage, AddressOf AcquirePageEventHandler
In VB gives: 'AcquirePage' is not an event of 'Object'
Any way around that?
I think the answer is to compile with Option Strict Off but without being able to reproduce the problem I can't be sure.
See: Early and Late Binding
Unable to find a solution to do this within VB, we went about it this way:
Added a new project: Silverlight C# Class Library
The constructor takes two arguments, the dynamic object and the address of the event handler, and performs the C# method of adding handlers:
public TwainHandler(dynamic twainSession, Delegate eventHandler)
{
twainSession.AcquirePage += eventHandler;
}
The C# library was built and the dll added as a reference to the VB project.
Dim t as TwainHandler = New TwainHandler(TwainSession, New AcquirePageDelegate(AddressOf AcquirePageEventHandler))
This way the C# library adds the handler for the event (which points to a method in our VB application) dynamically. If anyone has a better solution please share.

Why Can't I Inherit IO.Directory?

Why can't I create a class in VB.NET that inherits System.IO.Directory? According to Lutz Roeder, it is not declared as NotInheritable!
I want to create a utility class that adds functionality to the Directory class. For instance, I want to add a Directory.Move function.
Please advise and I will send you a six pack. OK nevermind I'm not sending you anything but if you come to the bar tonight I will hook you up and then beat you in pool.
From the Meta Data of .NET
namespace System.IO
{
// Summary:
// Exposes static methods for creating, moving, and enumerating through directories
// and subdirectories. This class cannot be inherited.
[ComVisible(true)]
public static class Directory
You cannot inherit from a Static Class.
Are you using C# 3.0 VB.NET 2008 -- then you could add an Extension Method
If you use the DirectoryInfo class, you will have access to a MoveTo function.
EDIT: I'll correct myself... The static Directory class already has a Move method.
I'd guess that Reflector isn't picking up the sealed attribute correctly for VB (or perhaps just not displaying it properly). If you look at the IL, it is sealed:
class public abstract auto ansi sealed beforefieldinit Directory