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 :)