vblang icon indicating copy to clipboard operation
vblang copied to clipboard

Implicitly casting IEnumerable(Of T) to List(Of T) should either be a compile time error or call ToList() on the input sequence.

Open ekolis opened this issue 4 years ago • 10 comments

If I write this code:

Dim list As New List(Of String)
list = List.OrderBy(Function(q) q)()

Then I get a rather cryptic runtime error about a "state machine". The actual problem is that I'm trying to implicitly cast an IEnumerable(Of String) to a List(Of String). But why should this be a runtime error? Can't it be a compile time error, same as any other invalid conversion? This is how C# behaves. Or if you want to be more VB-paradigmatic, why not call ToList() on the sequence implicitly when this cast is performed? At the very least, if it has to be a runtime error, why can't the error message be clearer, saying something about an invalid cast from IEnumerable(Of T) to List(Of T), rather than some sort of state machine?

Thanks! 🙂

ekolis avatar Dec 07 '20 17:12 ekolis

I'm pretty sure that I get warnings in my editor about this, which I'm sure is a very common pattern; I know I use it a lot.

What options are you running your VB compiler with?

why not call ToList() on the sequence implicitly when this cast is performed?

Because the VB compiler needs the framework to provide the necessary converter, which it apparently doesn't.

I think there is a good case to make that List(Of T) should have an implicit cast from IEnumerable(Of T).

pricerc avatar Dec 08 '20 04:12 pricerc

The code only compiles with Option Strict Off; with Option Strict On I get the following compilation error:

BC30512: Option Strict On disallows implicit conversions from 'IOrderedEnumerable(Of String)' to 'List(Of String)'.


I think there is a good case to make that List(Of T) should have an implicit cast from IEnumerable(Of T).

There is a significant difference between IEnumerable(Of T) and List(Of T) -- List(Of T) contains all the values in memory. Although IEnumerable(Of T) contains all the information needed to produce those values, they may not have been produced yet (although they might have been -- e.g. a compile-time expression of type IEnumerable(Of T) can reference a List(Of T)). Having an implicit cast from IEnumerable(Of T) to List(Of T) means the compiler wouldn't warn about the possibly unwanted evaluation of all these values.

Particularly when you're building up a LINQ query with multiple assignments, you only want the query to be evaluated at the end. There would be no way to write something like that if there were such an implicit cast.

Considering that using Option Strict On it's a compiler error, and the fix is rather simple (just call ToList()), I think this would be a bad idea.

zspitz avatar Dec 08 '20 06:12 zspitz

Oh, enabling Option Strict will make this a compile error? That's handy! I can enable Option Strict for just one code file by placing Option Strict On at the top of that file, right? I'm hesitant to enable it for the entire project because it's a large legacy codebase and doing so would probably expose numerous errors that do need to be fixed eventually but I wouldn't have time to fix them all right now...

ekolis avatar Dec 08 '20 14:12 ekolis

"Option Strict Off" setting does not allow you to find potential bugs at compile time.

It is recommended to make improvements on a module-by-module basis, even when there are changes to the module.

tfukumori avatar Dec 09 '20 02:12 tfukumori

Stay away from any fancy feature that use machine state or interface when you coding VB.net because VB.net intellisense isn't up to date on those feature, even Static N As Integer = 1 still use very old code from VS 2015 era.

RevensofT avatar Dec 17 '20 12:12 RevensofT

Static N as Integer =1 is just fine as far as I know, what is your problem with it?

jrmoreno1 avatar Dec 17 '20 17:12 jrmoreno1

What about support for VB.Net to have access to full library or at least DeserializeObject if not all functions. Serialization seems to be compatible.

paul1956 avatar Dec 17 '20 23:12 paul1956

@jrmoreno1 They still use very slow Activator instead anonymous static field like Static N as Integer without initialize.

RevensofT avatar Dec 21 '20 16:12 RevensofT

@RevensofT : not sure what you mean, part of the spec for Static is that it has to be thread safe and when assigned a value as part of the declaration, that code will only run once. Presumably they could replace the System.Activator.CreateInstance, with something else, but it wouldn't be a simple as Shared N as Integer.

jrmoreno1 avatar Dec 22 '20 00:12 jrmoreno1

@jrmoreno1 Just use Nullable(Of T) instead Activator , with nullable compiler can check static var has been initialized easily and faster then Activator .

RevensofT avatar Dec 22 '20 09:12 RevensofT