Thursday, July 15, 2010

How to create a generic List of anonymous types?

http://kirillosenkov.blogspot.com/2008/01/how-to-create-generic-list-of-anonymous.html


There was a question on one of the forums asking how to create a list of anonymous types given a single instance of an anonymous type:



var Customer = new { FirstName = "John", LastName = "Doe" };
var customerList = new List<????>();



My first reaction was to answer that this was impossible, and even if it was, for what purpose, but thankfully people replied before me, who knew better. I was amazed by these ingenious tricks. For example, Kael Rowan suggested:




var Customer = new { FirstName = "John", LastName = "Doe" };
var customerList = (new[] { Customer }).ToList();

customerList.Add(
new { FirstName = "Bill", LastName = "Smith" });



I think this is brilliant! This technique is called casting by example. Here's another implementation, using a "list factory":




static void Main(string[] args)
{
var Customer = new { FirstName = "John", LastName = "Doe" };
var customerList = MakeList(Customer);

customerList.Add(
new { FirstName = "Bill", LastName = "Smith" });
}

public static List<T> MakeList<T>(T itemOftype)
{
List<T> newList = new List<T>();
return newList;
}



They use generic type inference here to "name" the anonymous type to T and return a List of it.



This somewhat made me think of var as a black hole - once a type is being "converted" to a var, it can never come back explicitly (well, unless you want to cast :) It can reappear in another method as another "var" (casting by example) or be remanifested as inferred generic type parameter, but it can't get an explicit name ever again.



There was a discussion a while ago (between Wilco Bauwer, Rick Strahl and yours truly), whether C# should extend type inference to return types of methods, types of fields, properties etc. : Returning var from a method in C# 3.0 Generally it was agreed that this would not be a good thing to do, for various reasons. Eric Lippert gave a good summary of all the trouble it might bring:




· what if languages consume the method, which don't support type inference?


· how to store this in CLR metadata?


· how to detect versioning problems once you update your class?


· how to deal with two structurally identical types from different assemblies?


· etc.



My personal feeling about this all (which sort of corresponds with the general consensus), is that one shouldn't use anonymous types for more than trivial LINQ operations. If a type is going to be reused, give it a proper name and declaration. Anonymous types don't scale (at least, not in C# 3.0).



If there is ever going to be a C# feature to use var as a return type of members, this is going to be the first time ever I'll want the C# team not to implement a feature :)