[This post is part of a series, "wish-list for future versions of VB"]
IDEA: Unify the late-binder with the early-binder. Currently the late-binder uses VB8 rules, more or less, for its overload resolution. It should be updated to use VB10 rules, and indeed should continue to work exactly like the early binder (inasmuch as that makes sense). This would include improvements in things like delegate relaxation and generic inference for lambdas. For instance,
Sub f(ByVal x As Action)
Dim c As New C
c.f(Function() 1) ' works fine with the early-binder
Dim o As Object = c
o.f(Function() 1) ' causes runtime exception with the late-binder
SCENARIO: I don't think there are compelling scenarios here.
We never hear bug reports from users about these subtle differences between overload resolution in the early-binder and the late-binder. (We do get many bug reports from our own very dedicated group of QA testers, though...)
Stepping back, VB has historically gone down the path that "The late binder uses the run-time types of its arguments". This means the early-binder and the late-binder will never behave identically. By contrast, C# 4.0 has decided that "The late binder will use the compile-time types of its arguments if they are known (and not dynamic)". This means that its early-binder and late-binder can behave identically in many more scenarios. For instance,
Sub f(ByVal x As String) ' prints "string"
Sub f(ByVal x As Object) ' prints "object"
Dim arg As Object = "hello"
Dim c As New C
Dim o As Object = c
c.f(arg) ' early-binder looks at compile-time type of "arg" and prints "object"
o.f(arg) ' late-binder looks at run-time type of "arg" and prints "string"
// C# ...
object arg = "hello";
var c = new C();
dynamic d = c;
c.f(arg); // early-binder looks at compile-time type of "arg" and prints "object"
d.f(arg); // late-binder looks at compile-time type of "arg" and prints "string"
Provisional evaluation from the VB team: Even if we did want to implement this, we couldn't do it until we'd finished refactoring the compiler and rewriting it into VB.
It looks like I spoke too soon. There is now a customer bug about the difference between early and late behavior (but this time about conversions rather than overload resolution): Unboxing / Nullable InvalidCastException
Dim x1 = CType(2, Int64?)
Dim x2 As Int32? = x1
' Here the Int64? -> Int32? conversion happens at compile-time, and works
Dim y1 As Object = CType(2, Int64?)
Dim y2 As Int32? = y1
' Here the conversion can't happen at compile-time, and isn't implemented
' in Microsoft.VisualBasic.dll, so it throws InvalidCastException
Dim z1 As Object = CType(2, Int64?)
Dim z2 As Byte = z1
' Here the BoxedInt64 -> Byte conversion can't happen at compile-time, but
' it is implemented in Microsoft.VisualBasic.dll, and it works
Now with VB2010 SP1 there's a new wrinkle in the story. SP1 introduced a new feature called VBCore.
This embeds a small core component of Microsoft.VisualBasic.dll into the user's own executable. This means that VB apps no longer depend on shipping an external Microsoft.VisualBasic.dll
It is an enormously strong feature for the future growth of VB. It means that new platforms will be able to easily support VB, just as easily as they support C#, without having to do the extra work to port Microsoft.VisualBasic.dll. (Indeed, Microsoft.VisualBasic.dll simply can't be ported to frameworks like Phone or Micro Framework since they're so trimmed down). Its downside is that traditional VB functionality like "My" or "Left$" no longer work under VBCore. We cut them so as to make VBCore as tiny as possible.
Now imagine if things the conversion from Object to Int32? became a standard part of the language. It'd have to be implemented in Microsoft.VisualBasic.dll, and incorporated into VBCore. That's starting to be something of a headache...