I’m learning LINQ and VB and just spent an hour trying to access the fields of an anonymous type defined in a linq query. The key (I learned) is to convert the query to a list before you try to iterate through it with a for loop.
How to access property of anonymous type in C#?
This does not work: edit (this compiles, but intellisense does not recognize the type)
Dim varbl=from itm in collct select New With {.n=itm.Name} 'query here
for each returnedItem in varbl
returnedItem.n 'intellisense does not pick up the property names
next
But this does:
Dim varbl=(from itm in collct select New With {.n=itm.Name}).toList
for each returnedItem in varbl
returnedItem.n 'this works
next
Can somebody explain why/what is going on? The (otherwise helpful!) post above just says it is “Because of the way the compiler works, the following then should also work once you have created the list, because the anonymous types have the same structure so they are also the same type. I don’t have a compiler to hand to verify this though”
Well, I wasn’t going to answer since my VB is both very rusty and pretty out of date (eh, VB6 about a decade ago). But something did seem wrong here from a .NET perspective.
Your read on the answer you link to (which is incomplete in its explanation IMO) is wrong. It’s not that you need to put the anonymous object into a list, but that the querent there had been putting it into a
List<object>which meant that the compiler couldn’t tell what properties it had (it’s dealing with anobjectnot an object of the anonymous type in question, andobjectdoesn’t have aCheckedproperty).Anyway. I tried writing your initial attempt into some C# as:
Then I compiled and decompiled as VB.NET in reflector, which had my
Mainas:Which looks pretty much like your original, doesn’t it?
Well, it works; it compiles and runs and gives me correct answers.
The only thing I can think of is that maybe IntelliSense just wasn’t on the ball here. I have found that some times in the past, IntelliSense struggles to suggest the property names of anonymous types, and while I use SharpDevelop to code C# rather than VB (in whatever IDE it is that you use), this could be the case here – you actually had the correct code all along, but IntelliSense didn’t realise it.
At the end of the day, IntelliSense is pretty darn good, but it’s not the compiler, and it can’t spend as much resources doing stuff as the compiler for risk of slowing us down while we type.
Incidentally, you should not call
ToListunless you actually need a list for your purposes. Imagine ifcollctwas a loaded-as-needed enumeration that would return thousands of objects on the back of loading something from a database or file.If you don’t call
ToList, then you will start iterating through them as soon as the data for the first one arrives, and you’ll only need to use memory for a handful at a time.If you do call
ToList, then program will be stuck at that line until it’s loaded every single object into a massive list in memory, and only then start yourFor Each.Of course, there are times when you do need to be able to move back and forward though a list, or to know the count before you iterate, and then it’s certainly better to call
ToListthan to keep repeating theFor Each, but if you don’t know you need it, don’t use it.