Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't IEnumerable of anonymous types return a List<object> on ToList()?

Here is a simplified function that I want to create:

static List<object> GetAnonList(IEnumerable<string> names)
{
    return names.Select(name => new { FirstName = name }).ToList();
}

In that code block, I get the compiler error:

Error CS0029 Cannot implicitly convert type 'System.Collections.Generic.List<>' to 'System.Collections.Generic.List'

In the documentation for Anonymous types, it says that anonymous types are treated as type object. Why doesn't the C# compiler return a List<object> on names.ToList()?

Further more, why doesn't the following code cause an error? If List<<anonymous type: string FirstName>> cannot be converted to List<object>, then why can it be converted to IEnumerable<object>?

static IEnumerable<object> GetAnonList(IEnumerable<string> names)
{
    return names.Select(name => new { FirstName = name }).ToList();
}
like image 963
pwaivers Avatar asked Feb 15 '18 16:02

pwaivers


People also ask

Why can't I declare IEnumerable<anonymoustype> in a function?

You cannot declare IEnumerable<AnonymousType> because the type has no (known) name at build time. So if you want to use this type in a function declaration, make it a normal type. Or just modify your query to return a IENumerable<String> and stick with that type.

Should I return a list or an IEnumerable?

For example, by returning a List, you've taken away the ability to stream results which can have its own performance benefits. Your implementation may change, but the caller can always turn an IEnumerable into a List if they need to. Now that you've decided what the return type should be, you have to decide what the implementation should use.

How to avoid reflection when creating anonymous types?

The key to this is the fact that if you create an anonymous type with the same order, types and property names in two places the types will be reused. Knowing this you can use generics to avoid reflection. Clever. But really, if someone is going to go to that much trouble, they should just encapsulate the data in a declared class.

Are anonymous types unique to the scope that they are created in?

FYI: It is not strictly correct to say that anonymous types are unique to the scope that they are created in. Anonymous types which are structurally equivalent in the same assembly but used in two different methods are actually shared across those methods.


1 Answers

If List<<anonymous type: string FirstName>> cannot be converted to List<object>, then why can it be converted to IEnumerable<object>?

That's because IEnumerable<T> is covariant and List<T> is not. It has nothing to do with anonymous types.

If the code you wrote was to work you'd be able to use List<string> as List<object> and add anything to it breaking type safety.

You can make your code work by passing a generic type parameter to ToList call:

static List<object> GetAnonList(IEnumerable<string> names)
{
    return names.Select(name => new { FirstName = name }).ToList<object>();
}

But there is very little you can do with that outside of this method. You won't be able to access FirstName property unless you use reflection.

like image 96
MarcinJuraszek Avatar answered Oct 19 '22 18:10

MarcinJuraszek