Why does iteration of a list with an anonymous object work with an array but not with List<Object>?

Asked

Viewed 578 times

11

I tried the following iteration with C#:

var objects = List<Object>{
    new {Id = 2, Nome = "Wallace"},
    new {Id = 4, Nome = "Cigano"}
};

foreach (var user in objects) {
    Console.WriteLine ("Meu id é {0}", user.Id);
    Console.WriteLine ("Meu nome é {0}", user.Nome);
}

See the error in Dotnetfiddle

Made the following mistake:

Type object doesn’t contain a Definition for Id and not method Id Extension could be found.

But when I do it works:

var objects = new []{
    new {Id = 2, Nome = "Wallace"},
    new {Id = 4, Nome = "Cigano"}
};

If the new {} is Object I thought it was okay to use List<Object>, but I can only do this operation with Array.

1 answer

11


You are creating a list of Object. Look at the documentation of this class. See if there are members Id and Nome there in the documentation. It doesn’t. Will it magically appear? It won’t, it’s using a statically typed language. So the compiler tells you that you don’t have this that you want to use. You can play any object, including the internal classes created for the use of the Anonymous types, but when accessing the members of an object qualified as object can only access those available on type. It’s interface segregation.

In theory it would have a solution. It makes a cast for the real guy you’re putting on the list and then you’ll gain access to members of this guy. The problem is that you used an anonymous type (which is an internal class that the compiler generates and gives a name that only he knows), and to make a cast it is necessary to say the name of the type you want to promote. How can you, a programmer, do this? There is no way.

So the real solution is to create a collection that doesn’t need to specify the type of object it will contain. By C# fault (perhaps justifiable, I can’t say, but I can see some sense) only the array can do this. So the solution is to use it.

If you really need the list, then you can convert the array to the list that will work, because the compiler will handle everything that is needed and the cast, if necessary, it will be inserted by him with the name that he himself generated.

The var was created precisely for this. If you had the variable type printed, it would look something like this:

<>f__AnonymousType0`2[System.Int32,System.String][]

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

Or convert to list:

System.Collections.Generic.List`1[<>f__AnonymousType0`2[System.Int32,System.String]]

There was even a chat discussion on the use of dynamic to solve this. In fact the dynamic turns off compiler verification and you can use the concrete members of any existing object by bypassing C#type security. The same goes for access with the use of Reflection which gives you access to anything you want without the compiler having control. This is philosophically wrong, is to want to make C# turn PHP (roughly speaking), brings no benefit and mainly changes the semantics of what is asked in the question.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.