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();
}
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.
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.
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.
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.
If
List<<anonymous type: string FirstName>>
cannot be converted toList<object>
, then why can it be converted toIEnumerable<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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With