tags:

views:

105

answers:

3

I understood,normally generics is for compile time safe and allow us to keep strongly typed collection.Then how do generic allow us to store anonymous types like

List<object> TestList = new List<object>();
TestList.Add(new { id = 7, Name = "JonSkeet" });
TestList.Add(new { id = 11, Name = "Marc Gravell" });
TestList.Add(new { id = 31, Name = "Jason" });
+7  A: 

Because everything is (or can be boxed into) an object, and that's a List of objects.

Adam Wright
To be pedantic, it should say 'or can be **converted** into'.
SolutionYogi
+8  A: 

This works because object is the root type of all instances in .Net. Hence anything expression can be used for a location expecting an object because they all meet the basic contract of System.object.

For example the following is completely legal.

List<object> TestList = new List<object>();
TestList.Add(new { id = 7, Name = "JonSkeet" });
TestList.Add("Foo");
TestList.Add(42);
JaredPar
+5  A: 

Others already explained why your code works - your example is strongly typed, because everything is an object, but that means that it's not very useful. You cannot take elements from the list and access for example their Name property, because they are just object, so this cannot work in general.

However, it is possible to create a strongly typed List of anonymous types - it just needs to be done using a small utility method like this:

static List<T> CreateList<T>(params T[] items) {
  return items.ToList();
}

The problem is that you can't call a constructor without providing the name of the type. When calling a method, C# can infer the type parameter, so you can write this:

var testList = CreateList(
  new { id = 7, Name = "JonSkeet" },
  new { id = 11, Name = "Marc Gravell" });
testList.Add(new { id = 31, Name = "Jason" });

This is perfectly type-safe and you can for example write testList[0].Name to get the name of the first person. If you try writing something like testList.Add(42), you'll get a compile-time error, because the list is strongly typed to contain only anonymous types with id and Name properties.

Tomas Petricek
+1 Fascinating, and eloquently said. I do find myself wondering what real-world scenario would you want to be using lists of "anonymous objects" other than as a form of "obfuscating" the code. Another "aha" moment waiting there, I'm sure :)
BillW
@BillW: It's a convenience thing; it saves you from having to define your own little helper type. Now that there is a standard Tuple type in the framework, the usage case for jumping through hoops to make lists of anonymous type is much weaker.
Eric Lippert
Incidentally, this technique is often called "cast by example". If you search for that phrase on SO you'll find a number of questions where people attempt to build anonymous-typed lists, dictionaries, and so on.
Eric Lippert
@Eric Lippert: Yes, I discovered the trick independently some time ago: http://tomasp.net/articles/cannot-return-anonymous-type-from-method.aspx :-)
Tomas Petricek
I am quite wondering!!!
@Eric Lippert: Actually, I thought that "cast by example" refers only to the unsafe use (as in my article). The code here (to create lists/dictionaries/etc.) is fully type-safe - it is just simulating type inference for constructors (which isn't supported) using a method call... (BTW: Adding type inference for constructor calls would be nice!)
Tomas Petricek
@Tomas: I guess that adding that kind of type inference would require inference on the return type. Not sure how hard that is to add to the language, but I suppose there's something bad/difficult about it because it was left out so far.
Martinho Fernandes
@Martinho: It shouldn't be difficult (of course, C# is more complex than most of the people expect, but still...). You can already omit type parameters on method calls - e.g. `a.Foo(1)` instead of `a.Foo<int>(1)`. I'm asking for similar thing for constructors - something like `new List<?> { 1, 2, 3 }` instead of `new List<int> { 1, 2, 3 }`. (the `?` would be a special symbol - something like `var`).
Tomas Petricek
@Tomas: yes, for those examples it would work and it would be nice, but how would you do type inference on `var foo = new List<?>()`? Possible? No doubt. F# does it, Haskell does it. Worth the C# team's effort? I don't know. I'm not sure they would be happy shipping a feature that covers half the cases, especially when calling default constructors can be rather common :(
Martinho Fernandes
@Martinho: I wouldn't allow that - type inference in C# works in the scope of expressions only. F# or Haskell use very different approach. My case is actually questionable, because it uses inference based on the `Add` method (used by object initializers) and not the constructor directly, so that would require some effort. I guess it's not all that useful, but it would be nice to have :-).
Tomas Petricek