Late Binding: Expecting error but not getting it - vb.net

I wrote the below code to understand Late Binding with Option Strict ON. With OPTION STRICT ON, I was expecting an error in the statement: o = New Car(). But not getting any error. Isn't that strange? Its clearly mentioned in the MSDN documentation on Option Strict that when ON it prevents late binding - gives a compile time error. So what is happening here....can someone pls help?
Option Strict On
Module Module1
Sub Main()
Dim o As Object
o = New Car() 'Expecting error here but not getting
Console.ReadLine()
End Sub
End Module
Class Car
Public Property Make As String
Public Property price As Integer
End Class

There's nothing at all wrong or inappropriate about assigning an object of a derived type to a variable of a base type. That's exactly what allows for polymorphism, which is a cornerstone of OOP. What constitutes late binding is trying to access a member of the derived type via a reference of the base type.
The compiler only knows the type of the reference, so it only knows about members of that type. If you try to access a member that doesn't belong to that base type type then the compiler cannot confirm that that access is valid. Type-checking must be deferred until run time, when the type of the object is determined and it is confirmed whether that member actually exists.
Early binding is when the the existence of a member on a type is confirmed at compile time, while late binding is when it's done at run time. If there is no member access then there is no binding at all to be early or late.
Dim c As New Car
Dim o As Object = New Car
c.Make = "Ford" 'Early binding
o.Price = 20000 'Late binding
In the code above, the setting of the Make property is early-bound because Make is a member of the type of c. On the other hand, the setting of Price is late-bound because Price is not a member of the type of o so confirmation that the object has such a member must be deferred until run time.

Related

Type 'Collection' is not defined vb BC30002

I am attempting to migrate a legacy vb.net application to .net standard and turn it into a nuget package. A good amount of it has been straight forward. I am currently hung up on this error caused by functions like this.
Public Property ErrorMessages As Collection
Get
ErrorMessages = _errorMessages
End Get
Set(value As Collection)
_errorMessages = value
End Set
End Property
If i import System.Collections.ObjectModelCollection(Of T) it is asking me for a type and i am unsure how to proceed. It turns my code into
Collection(Of,) and expects a second argument. Has anyone faced this before? Do i use a different import statement or how is this dealt with in vb now?
You should almost certainly replace Collection with Dictionary(Of TKey, TValue), using the dictionary type from the System.Collections.Generic namespace.
Once again, this requires you to fill in the genetic type arguments TKey and TValue with the actual types. You need to figure out from context which type fits the collection. The value of TKey is probably String since that’s the only key type VB6’ collections properly support. And given the name (ErrorMessages), TValue is probably String as well.

Late Binding in VB

From what I have read so far, late binding is defining a variable as Object and then assigning it to the actual object later which is actually done at run time. I don't understand the point to that. Maybe this is the Java in me, but doesn't that limit the functionality to what is just in Object? It is like saying, "I want the potential of the extra stuff, but I don't want to have access to it." Is there an actual purpose for late binding in VB, or Java for that matter, that I'm overlooking?
You have it backwards. By using early binding you are limiting yourself to just the members of the type of the variable. With Option Strict On, a variable declared as type Object will only allow you access to members of type Object, regardless of the type of the actually object it refers to. With Option Strict Off, you can access a member of any name on a variable of type Object and the compiler won't complain. It's only at run time that any type checking is done so, as long as the actual object assigned to the variable has a member with that name, the code will run.
Probably the most common use for late binding is Office Automation. There are other options now but, in the past, if you referenced an Office library and used the specific types it contained, facilitating early binding, then you were limited to that specific version of Office. In order to support multiple versions, you had to forgo the reference, declare all your variables as type Object and use late binding. As long as the version of Office present at run time included the specified members on the objects used, the code would run without issue.
By the way, late binding doesn't require using type Object, although it is probably the most common. It just means that the reference is a less derived type than the object and you use a member of the object's type that the reference's type doesn't have, e.g. you use type Control and then use a member specific to type Button.
What I seen - some early .NET adapters-developers were doing is - they were using late binding instead on interfaces. They would declare two or more types
Public Class Handler1
Public Sub Execute()
' do something
End Sub
End Class
Public Class Handler2
Public Sub Execute()
' do something else
End Sub
End Class
And they would stick this thing into session object
If someting = 1 Then
Session("Handler") = New Handler1()
Else
Session("Handler") = New Handler2()
End If
And then, to process something they would do
Session("Handler").Execute()
There we go. This is not pretty or smart. But that was instead of proper programming like this (Imagine handlers implement IHandler interface with method Execute)
Dim h As IHandler = TryCast(Session("Handler"), IHandler)
If h IsNot Nothing Then
h.Execute()
End If
Here is where downfall of late binding starts: In the case of late binding, someone, somewhere, can rename a method Execute and compile code nicely. Release. And only then, at runtime, get a problem.
Late binding was good when we used to deal with interop and COM. Other than this, it is detrimental.

None Shared member requires an object reference

I'm having a problem because I changed my code from vb6 to .net and I cant seem to sort out this issue I am having. Please assist.
The error message I'm getting:
Error 5 Reference to a non-shared member requires an object reference.
This is happening quite a few places in the code. This is my code. The problem is where it says FrmInvItem.Inv.`
Option Strict Off
Option Explicit On
Public Class ClsInv
Public Function RunProcess(ByVal ConnectStr As String, ByRef Parstr As String) As Integer
Dim frmInvIt As frmInvItem
RunProcess = frmInvItem.Inv(ConnectStr, Parstr)
frmInvIt.Close()
End Function
I assume Inv is not shared, but you are calling it without an instance of the class in which it is. So you either have to make it shared or create an instance of frmInvItem:
Dim frmInvIt As New frmInvItem() ' create instance
RunProcess = frmInvIt.Inv(ConnectStr, Parstr) ' use it on this instance
frmInvItem is the class, you can call a method via classname only if the method is shared.
Shared procedures are class methods that are not associated with a
specific instance of a class. For example, the Cos method defined
within the Math class is a shared method. You can call a shared
procedure as a method of an object or directly from the class.
You are running a method called Inv on a the frmInvIt without creating an instance.
You should create an instance to run your method against:
http://msdn.microsoft.com/en-us/library/77s47661.aspx

Option Strict and DefaultValueAttribute

Having just spent the past several hours trying to work out why my Xml Serialization code was not working. Consider the following:
<DefaultValueAttribute(False)>
Public Property UserName() As String
Why is this allowed regardless of option strict being on (or not)?
Quite simple. The DefaultValueAttribute has an overload which accepts boolean values so it will work with or without Option Strict on.
Check this page for more information DefaultValueAttribute Class.
The answer is that VS does not type check default values for VB.NET, regardless of OptionStrict or not.
<DefaultValueAttribute(False)> is valid because the attribute definition is really a constructor and not a type definition, as such it's type is DefaultValueAttribute and not a return type of boolean. Furthermore the .Value property of the DefaultValueAttribute is of type Object and hence it's type cannot be compared either, as such the very existence of DefaultValueAttribute violates Option Strict On and hence Option Strict ignored for the scope of DefaultValue Attributes.

Casting Early bound object type into Late bound object type

I've got a piece of code in a project (MyProject) that contains early bound object from a referenced assembly (We'll call it CommonAssembly):
Dim myObject As CommonAssembly.MyEarlyBoundType
now I have another assembly that is dynamically loaded because it is not present in all projects:
Dim myLateBoundObject As Object = AppDomain.CurrentDomain.CreateInstanceAndUnwrap("Utils", "Utils.MyLateBoundType")
MyLateBoundType derives from CommonAssembly.MyEarlyBoundType, and I want to cast myObject to myLateBoundObject and then programmatically invoke the additional member methods
via reflection.
I'd have thought that by extracting the type of myLateBoundOject and casting myObject into myLateBoundObject, that'd work, but both CType() and DirectCast() methods won't accept the extracted type citing a "Keyword does not name a type" error:
myLateBoundObject = DirectCast(myObject, GetType(myLateBoundObject))
I'm not entirely sure why a dynamically loaded type cannot be used against the DirectCast (pretty sure it's not type saftey checked?) method, since if Utils.MyLateBoundType was referenced in "MyPrjoect", I could execute:
myLateBoundObject = DirectCast(myObject, Utils.MyLateBoundType)
without any problems - but this is not a dynamic solution.
Any suggestions?
Cheers,
Yum.
Yeah, that's not going to work like that. Any attempt you'd make in your code to cast to the dynamically loaded type will make your program have a non-dynamic dependency on the assembly.
You should use an interface type. Declare that type, with all the properties and methods you'd want to have available in your main program, in a separate assembly. Both your main program and your plug-in will have a dependency on it. The dynamic type should inherit it to provide the implementation. You can now cast the return value of CreateInstance to that interface type.