Support type inference in Static variable declarations

Topics: VB Language Design
Jun 21, 2014 at 1:39 AM
Now in Visual Basic, you can write:
Dim A = New List(Of Integer)()
Instead of:
Dim A As List(Of Integer) = New List(Of Integer)()
And it will infer the type of A automatically (when having Option Infer On).

But writing this inside a method, will generate a compile error:
Static A = New List(Of Integer)()
Although this will work:
Static A As List(Of Integer) = New List(Of Integer)()
It would be nice if type inference in static local variable declarations become possible in VB.NET.
Jun 21, 2014 at 7:23 AM
How about Static A As New List(Of Integer)?
Jun 21, 2014 at 1:31 PM
Consider this case:
Dim A = IO.Stream.Null
Or this:
Dim A = IO.File.OpenRead(".\Data.txt")
Coordinator
Jun 21, 2014 at 9:35 PM
Hey Shayan_To,

Thanks for the suggestion. We did discuss this last year but decided it against it most because of the risk of backcompat breaks in late-binding scenarios:
Imports System.Console

Module Program

    Class C
        Sub M()
            WriteLine("C.M")
        End Sub

        Shared Function Create() As C
            Return New D()
        End Function
    End Class

    Class D
        Inherits C

        Overloads Sub M()
            WriteLine("D.M")
        End Sub
    End Class

    Sub Main()
        Static obj = C.Create()

        ' Today this prints "D.M" but with static local type inference
        ' it would print "C.M".
        obj.M()
    End Sub
End Module
That was, as I recall, the main reason we decided not to fix this in "Roslyn".

Regards,

Anthony D. Green, Program Manager, Visual Basic & C# Languages Team
Jun 22, 2014 at 5:56 PM
Option Infer On behaves differently from the Option Strict Off dialect of VB, but that dialect is so loosy-goosy in so many ways that it's essentially deprecated. There are some cases where variable type inference is dubious, but those could IMHO best be resolved by only allowing type inference for certain kinds of expressions, such as those which are the result of a typecast, a static factory ,method whose return type precisely matches the type containing the factory, or a new expression (though the latter already has a convenient syntax).
Coordinator
Jun 23, 2014 at 5:36 AM
Edited Jun 23, 2014 at 5:36 AM
Option Infer On and Option Strict Off behave differently because they are different things. They just happen to both intersect in some places but they're otherwise unrelated.

We shouldn't design the language based on the prevailing winds of what people think is popular or proper convention at the moment because conventions change. In 2002 someone might have said "Optional parameters are legacy and goofy and essentially deprecated" and we could have designed the language from that point simply not caring about them, potentially introducing all kinds of warts, and in 2010 when C# got optional parameters and the .NET ecosystem started to appreciate them more we'd have a language which was poorly designed around a now important scenario because people thought they were "essentially deprecated" ten years ago. In 2005 late-binding is "essentially deprecated" except for legacy purposes with COM interop and in 2010 it's the only way to take advantage of the Dynamic Language Runtime, the centerpiece of the entire release. Will it be important in VB Interactive, VB scripting -who knows.?

At some point someone probably thought static local variables were "essentially deprecated" and it may even be that when we designed and implemented Option Infer in 2008 we looked at the work of making static local variables type-inferred and someone said "Does anyone really use those anymore? Why not just use a field?" and we just neglected them. And now we find ourselves six years later dealing with the semantics of a neglected feature that Shayan_To and I both happen to find useful wishing we could make it right. I think the lesson from that is that we must always think about all of the features in the language, even the seemingly unpopular ones and not design around them.

I'd really love to make static local type inference work as it always should have; we'll either have to decide we're ok taking the breaking change or come up with a non-breaking way to fix it. Neither option is going to leave everyone happy though :(

-ADG
Jun 30, 2014 at 6:39 PM
ADGreen wrote:
We shouldn't design the language based on the prevailing winds of what people think is popular or proper convention at the moment because conventions change. In 2002 someone might have said "Optional parameters are legacy and goofy and essentially deprecated" and we could have designed the language from that point simply not caring about them, potentially introducing all kinds of warts, and in 2010 when C# got optional parameters and the .NET ecosystem started to appreciate them more we'd have a language which was poorly designed around a now important scenario because people thought they were "essentially deprecated" ten years ago. In 2005 late-binding is "essentially deprecated" except for legacy purposes with COM interop and in 2010 it's the only way to take advantage of the Dynamic Language Runtime, the centerpiece of the entire release. Will it be important in VB Interactive, VB scripting -who knows.?
A big reason I would regard Option Strict Off as essentially deprecated is that its behavior is in many cases so vaguely defined that I doubt that there are very many people--if any--who understand the corner cases well enough to determine whether two pieces of code that are generally equivalent are always equivalent, or may in some weird situations behave differently.

I appreciate that there are cases where dynamic binding is useful; C# handles that very nicely with the dynamic keyword, and VB.NET could benefit from a similar feature. I think one of the biggest mistakes in the effort at easing VB6-to-VB.NET migration was mapping all uses of Variant and unknown-type objects to Object. If VB6 had kept Variant, and added an AnyObject keyword, those could have behaved as Object does in the Option Strict Off dialect, without having had to add weird behaviors to variables and expressions of type System.Object
At some point someone probably thought static local variables were "essentially deprecated" and it may even be that when we designed and implemented Option Infer in 2008 we looked at the work of making static local variables type-inferred and someone said "Does anyone really use those anymore? Why not just use a field?" and we just neglected them. And now we find ourselves six years later dealing with the semantics of a neglected feature that Shayan_To and I both happen to find useful wishing we could make it right. I think the lesson from that is that we must always think about all of the features in the language, even the seemingly unpopular ones and not design around them.
I wouldn't mind static local variables as syntactic sugar for a means of declaring a field within a function, but I don't like having compiler-generated fields which are completely inaccessible to user code. If it's necessary e.g. for an object to take a snapshot of its state and then later reload its state from the snapshot, such code won't be able to access any state which has gotten buried in compiler-generated fields.
I'd really love to make static local type inference work as it always should have; we'll either have to decide we're ok taking the breaking change or come up with a non-breaking way to fix it. Neither option is going to leave everyone happy though :(
The thing I would want to see with type inference, static or not, would be a distinction between an expression which happens to have a particular type, and an expression which "clearly" has a particular type (i.e. fits a pattern of expressions whose type is considered "clear"). That having been said, I'd like to see an expanded use of "let" variables, with semantics I've described elsewhere.