Core3: Dynamic pseudo-type (scoped late binding)


[This post is part of a series, “wish-list for future versions of VB“]

 


IDEA: Scoped late binding through a dynamic pseudo-type. Add a new pseudo-type called either Dynamic or Variant. It would be exactly the same type as Object, but it would suppress errors/warnings about late-binding in any expression that it’s used. Also, when we import COM functions that currently return Object, we’d import them instead as returning Dynamic. We’d also use the same DynamicAttribute that C# uses when reading or writing metadata.


 


SCENARIO: You want to have late-binding in your code, but want to leave Option Strict On. Currently there’s no way to do this. The dynamic pseudo-type would allow it, as shown below. In the following we’ve written “As Dynamic” explicitly to show what type we’re getting back (and it suppresses errors/warnings on “cell.ColumnWidth”), but if we omitted it then “cell” would still be inferred as Dynamic.


    Option Strict On


    Dim excel = New Microsoft.Office.Interop.Excel.Application


    excel.Visible = True : excel.Workbooks.Add() : excel.Worksheets.Add()


 


    Dim cell As Dynamic = excel.Cells(1, 1)


    cell.ColumnWidth = 15


 


 


Note that this wouldn’t quite be the same as the C# “dynamic” pseudo-type. The C# rules say “If dynamic is involved anywhere then do a late-bound call”. But the existing VB rules say “If binding failed, and it failed due to narrowings from Object, then do a late-bound call”. We would stick with the VB rules for our dynamic pseudo-type. For instance,


 


        Dim d As Dynamic = “hello”


        Console.WriteLine(d)  ‘ early-bound call in VB


 


        dynamic d = “hello”;


        Console.WriteLine(d); // late-bound call in C#


 


 


ALTERNATIVE IDEA: Instead of using a pseudo-type to suppress errors/warnings about late-binding, we could instead use different operators:


        cell~.ColumnWidth = 15


        ‘ The “~.” operator is like “.” but it suppresses
        ‘ warnings/errors about late-binding


 


 


An entirely different way to achieve “scoped late-binding” is to add #Pragma directives to VB which could suppress arbitrary errors/warnings in any chunk of code. I’ll take about this later (“Req33: Pragmas, e.g. to suppress warnings”).


 


 


Provisional evaluation from VB team: VB has always had its own form late-binding via Object. While it’s a shame that you can’t scope your late-binding smaller than file granularity, this doesn’t seem a big enough problem to justify a second form of late-binding.

Comments (13)

  1. Kyralessa says:

    I guess I’m wondering what the advantage is over just implementing the Dynamic keyword in VB exactly the same as in C#, in such a way that it would be compatible with Option Strict On.  (That is, Option Strict violation errors wouldn’t be raised on things typed as Dynamic.)

    I assume you’d have to specifically type something as Dynamic if Option Infer were on.

    I think the alternate idea of using ~. looks dreadful.

    Perhaps another alternate idea:  The ability to declare a LateBound (or Dynamic) block, similar to how C# declares an unsafe block?  E.g.:

    LateBound

       ‘ do late-bound stuff

    End LateBound

    I’d be in favor of just about anything that would keep people from having to make an entire file late-bound.  Just about anything outside of that ugly ~. syntax.  🙂

  2. Dzonny says:

    I really want to see something like C# Dynamic in VB. Lets call it Variant it’s move Visual Basic :-).

    I preffer VB rules rather than C# rules.

    Operator vs. pseudo type:

    Both have advantages.

    With pseudo type you can do

    Function foo(ByVal x As ISomething1)

    Function foo(ByVal x As Something2)

    Function foo(ByVal x As ISomething3)

    Dim x As Dynamic = GetSomethingFromSomewhere

    foo(x) ‘Runtime decession which overload will be called.

    With operator you can do

    Dim x As IEnumerable(Of Something) = GetSomethings

    x~Add(GetSomething)

    Please, do not use "~." It’s weird. What about just "~"? (I know with "~." you can have "~!" as well, but how many people use "!").

    What about having both – Variant and "~"?

    You may also consider something like

    Dim x As Object, mrml As Long

    foo(~x) ‘Means deffer decision which foo to call for runtime

    foo(~x,mrml) ‘Means deffer decision which foo to call for runtime, but behave like when argument2 is early bound

    foo~(x,mrml) ‘Means deffer decision which foo to call to runtime

  3. Reinier Post says:

    I really really like the ~ idea.  It’s concise and it marks the late-bindedness where it matters, not in some other place the programmer may forget to check when writing or debugging the code.  Typing all those ~s could be tedious, but the impact is relatively easy to verify by taking existing non-strict code, adding all the ~s where required, and seeing how bad it is.

  4. taiwoa@live.com says:

    Didn’t VB3 and VB4 use the "!" operator for this?

  5. Dzonny says:

    The ! operator has slightly different purpose. In VB2005/8/10 it looksproperty with following signature:

    Public Default Property Whatever (ByVal whatever As String) As Whatever

    on the object on left side. On right it expects identifies and passes it as index parameter to the property.

    Maybe VB canoverload it for dynamic purposes.

  6. Dzonny says:

    The ! operator has slightly different purpose. In VB2005/8/10 it looksproperty with following signature:

    Public Default Property Whatever (ByVal whatever As String) As Whatever

    on the object on left side. On right it expects identifies and passes it as index parameter to the property.

    Maybe VB canoverload it for dynamic purposes.

  7. Kevin Ryall says:

    This would be very useful – scoping late binding / dynamic typing at the file level means that you lose type checking for all variables, instead of the (usually) one or two you actually need to be dynamic. Even using partial classes to isolate the late bound methods in a class leaves other variables (string, etc.) without compile-time type-checking.

    I have a class that interacts with a legacy VB6 COM+ application using late binding – used because the IIDs change occasionally, but the relevant method signature never does so early binding would break unnecessarily  (even with binary compatibility VB6 doesn’t entirely preserve interface IDs). To do this I have a file with Option Strict switched off (a massive violation of our standards) just to allow me to late bind to the COM class variable. The other variables in the class (mainly primitives – especially strings) I still want to use early binding with, but I’m forced to use late binding with them all because the binding setting is file scoped.

    The ideal scoping for late binding is the variable itself – anytime I have ever used this it was specific variables – generally just one or two – and I don’t like losing early type checking for everything else. It’s not a huge issue because I don’t use late binding much in VB, but it would make the language cleaner if we could target late binding where it logically applies – at the variable.

  8. MarkJ says:

    Thanks for considering the idea. I still think it would be really nice to be able to scope late binding at the variable level. It's one of the remaining things that justifies snobbery about VB.

    Can I also add a couple of links? Not spam, honest!

    Everyone who likes this idea, please vote for it on Microsoft Connect and maybe it'll get implemented. connect.microsoft.com/…/please-give-vb-net-some-equivalent-for-c-dynamic-with-option-strict-on  

    Also, there's some more discussion about this on StackOverflow – this discussion prompted me to add the issue on Microsoft Connect stackoverflow.com/…/vb-net-equivalent-for-c-dynamic-with-option-strict-on

  9. JeroenH says:

    I'm all for it. As MarkJ says, this is one of the remaining gaps between VB.Net and C#.

  10. CraigJ says:

    Let me BEG and PLEAD with the VB team to solve this! Option Strict On is an absolute must for compile-time checking; having to turn this off to get the goodness of late binding totally feels like one of those legacy workarounds and is just goofy and awkward. And honestly what is the problem with having two late-bound scenarios – backwards compatibility for the Option Strict Off crowd (still not sure who that is any more) and the Dynamic keyword (or equivalent) to use with Option Strict On? Development of the DLR obviously indicates the cyclical resurgence of late binding/duck-typing so why not just implement Dynamic as the clear accessibility path to the DLR? Seems there is a REAL difference between casual (dare I say lazy), old-style late binding and deliberate, explicit late binding when the developer clearly indicates his intent to late-bind right alongside early-bound calls. This dovetails with the clear intent of supporting multiparadigmatic features in the flagship languages and brings VB in line with the advances made in C# (which just leap-frogged VB for the first time in its late binding support).

  11. Sabroni says:

    We need this if VB is to actually support asp.net mvc properly.

  12. Mark says:

    It would be really nice if "As Dynamic" could make it into VB.NET, once the Roslyn dust settles, since the better scoping for late binding is about the only thing I really keep missing in VB.NET vs. C#.

  13. Anthony Parkinson says:

    Just one more vote for the variable level scoping of late binding.  We insist on Option Strict On in all our code to prevent sloppy stuff.  There are however situations where a single variable that is late bound would be very useful (think a de-serialized JSON string for example).