477

In C# 3.0 you can create anonymous class with the following syntax

var o = new { Id = 1, Name = "Foo" };

Is there a way to add these anonymous class to a generic list?

Example:

var o = new { Id = 1, Name = "Foo" };
var o1 = new { Id = 2, Name = "Bar" };

List<var> list = new List<var>();
list.Add(o);
list.Add(o1);

Another Example:

List<var> list = new List<var>();

while (....)
{
    ....
    list.Add(new {Id = x, Name = y});
    ....
}
leppie
  • 115,091
  • 17
  • 196
  • 297
DHornpout
  • 6,400
  • 4
  • 25
  • 20
  • 2
    Note that all the objects must be typed the same in the array. Rarely you may need to help with a cast, especially for nulls `new[] { new{ Id = (int?)null, Name = "Foo" }, new { Id = (int?)1, Name = "Foo" }}` – AaronLS May 24 '13 at 19:25
  • 1
    anonymous types are designed to be used as temporary storage, in most cases you would create them in LINQ select statement using Select(i=>new {i.ID,i.Name}); which would return a IEnumerable of the correct type if you redefine your while clause into a LINQ.Where statement you shouldn't ever need the list and if you did you can then just call ToList on it – MikeT Nov 27 '14 at 11:00

22 Answers22

490

You could do:

var list = new[] { o, o1 }.ToList();

There are lots of ways of skinning this cat, but basically they'll all use type inference somewhere - which means you've got to be calling a generic method (possibly as an extension method). Another example might be:

public static List<T> CreateList<T>(params T[] elements)
{
     return new List<T>(elements);
}

var list = CreateList(o, o1);

You get the idea :)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • The correct syntax (at least in 3.5) is var list = new[] {o, o1}; – DHornpout Mar 04 '09 at 22:43
  • 37
    @DHornpout: That would give an array, not a List. – Jon Skeet Mar 04 '09 at 22:47
  • 1
    What version are you using? This is the compiler error I got Error 1 'System.Array' does not contain a definition for 'ToList' and no extension method 'ToList' accepting a first argument of type 'System.Array' could be found (are you missing a using directive or an assembly reference?) – DHornpout Mar 04 '09 at 22:52
  • 27
    @DHornpout: Do you have "using System.Linq;" at the top of your file? ToList is a LINQ operator. – Jon Skeet Mar 04 '09 at 23:06
  • 6
    Got it.. Need to include "using System.Linq". Thanks. – DHornpout Mar 04 '09 at 23:13
  • 3
    It does seem an inconsistency in Visual Studio, that intellisense isn't more helpful in uncovering missing includes of assemblies with referenced extension methods (same as referenced types). – LOAS Jan 04 '12 at 12:21
  • Why do I get "object does not have 'x' property"? I use this method to pass an anonymous list to my view in ASP.NET MVC and there, I get this error. – Saeed Neamati Oct 24 '12 at 15:22
  • @SaeedNeamati: I can't possibly tell without seeing your code. Sounds like you should ask a new question. – Jon Skeet Oct 24 '12 at 15:27
125

Here is the answer.

string result = String.Empty;

var list = new[]
{ 
    new { Number = 10, Name = "Smith" },
    new { Number = 10, Name = "John" } 
}.ToList();

foreach (var item in list)
{
    result += String.Format("Name={0}, Number={1}\n", item.Name, item.Number);
}

MessageBox.Show(result);
Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
Dutt
  • 1,251
  • 1
  • 8
  • 2
80

There are many ways to do this, but some of the responses here are creating a list that contains garbage elements, which requires you to clear the list.

If you are looking for an empty list of the generic type, use a Select against a List of Tuples to make the empty list. No elements will be instantiated.

Here's the one-liner to create an empty list:

 var emptyList = new List<Tuple<int, string>>()
          .Select(t => new { Id = t.Item1, Name = t.Item2 }).ToList();

Then you can add to it using your generic type:

 emptyList.Add(new { Id = 1, Name = "foo" });
 emptyList.Add(new { Id = 2, Name = "bar" });

As an alternative, you can do something like below to create the empty list (But, I prefer the first example because you can use it for a populated collection of Tuples as well) :

 var emptyList = new List<object>()
          .Select(t => new { Id = default(int), Name = default(string) }).ToList();   
Paul Rouleau
  • 811
  • 6
  • 4
  • 2
    Thanks for the idea. A suggestion, you can avoid allocating a dummy list if you use `Enumerable.Empty().Select(o=>definition).ToList()` – BrainStorm.exe Jan 25 '19 at 17:01
54

Not exactly, but you can say List<object> and things will work. However, list[0].Id won't work.

This will work at runtime in C# 4.0 by having a List<dynamic>, that is you won't get IntelliSense.

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
Jeff Moser
  • 19,727
  • 6
  • 65
  • 85
  • It's not strongly-typed, though, in the sense that you'll have no compiler intellisense support for the items in the list. – Joel Coehoorn Mar 04 '09 at 22:12
  • 3
    I didn't say it was a *great* idea, but that it was possible :-) There could be a need if storing objects from Ruby for example. – Jeff Moser Mar 05 '09 at 14:40
  • 3
    But in those cases the source type is dynamic after all, it makes no sense to use a List for anonymous types. – Dykam Oct 30 '09 at 09:13
  • 1
    Very helpful. Especially if the list has to be defined before anonymous items are added into it. – Karlth Jul 08 '14 at 11:25
41

If you are using C# 7 or above, you can use tuple types instead of anonymous types.

var myList = new List<(int IntProp, string StrProp)>();
myList.Add((IntProp: 123, StrProp: "XYZ"));
Bassem
  • 2,736
  • 31
  • 13
24

I usually use the following; mainly because you then "start" with a list that's empty.

var list = Enumerable.Range(0, 0).Select(e => new { ID = 1, Name = ""}).ToList();
list.Add(new {ID = 753159, Name = "Lamont Cranston"} );
//etc.

Lately, I've been writing it like this instead:

var list = Enumerable.Repeat(new { ID = 1, Name = "" }, 0).ToList();
list.Add(new {ID = 753159, Name = "Lamont Cranston"} );

Using the repeat method would also allow you to do:

var myObj = new { ID = 1, Name = "John" };
var list = Enumerable.Repeat(myObj, 1).ToList();
list.Add(new { ID = 2, Name = "Liana" });

..which gives you the initial list with the first item already added.

Rostov
  • 2,516
  • 2
  • 23
  • 17
  • 2
    You don't need to start with an empty list - you can do Range(0,1) and make your first object in the select statement be.. the first object. – Matthew M. May 28 '14 at 16:02
  • 2
    You don't need to start with an empty list -- in the case where you know what the first item is (as in the example) then you're right in your comment. Many times though I use this for parsing an intermediate file / data source and don't access the first true item until using it in a LINQ projection scenario (and thus don't need to account for skipping the first record). – Rostov May 29 '14 at 17:19
24

I guess

List<T> CreateEmptyGenericList<T>(T example) {
    return new List<T>();
}

void something() {
    var o = new { Id = 1, Name = "foo" };
    var emptyListOfAnonymousType = CreateEmptyGenericList(o);
}

will work.

You might also consider writing it like this:

void something() {
    var String = string.Emtpy;
    var Integer = int.MinValue;
    var emptyListOfAnonymousType = CreateEmptyGenericList(new { Id = Integer, Name = String });
}
Luis Perez
  • 27,650
  • 10
  • 79
  • 80
erikkallen
  • 33,800
  • 13
  • 85
  • 120
21

You can do this in your code.

var list = new[] { new { Id = 1, Name = "Foo" } }.ToList();
list.Add(new { Id = 2, Name = "Bar" });
MalachiteBR
  • 560
  • 4
  • 10
13

I checked the IL on several answers. This code efficiently provides an empty List:

    using System.Linq;
    …
    var list = new[]{new{Id = default(int), Name = default(string)}}.Skip(1).ToList();
MEC
  • 1,690
  • 1
  • 17
  • 23
  • 1
    Any reason to reject my edit? Following answer returns `IEnumerable`, whereas my version returns `List`, exactly what OP has asked. – Necronomicron Dec 30 '15 at 22:09
  • 1
    I prefer this approach, or even one closer to [this answer](http://stackoverflow.com/a/15749796/393280): `new object[] { }.Select(o => new { Id = default(int), Name = default(string) }).ToList()` – palswim Feb 26 '16 at 22:41
12

In latest version 4.0, can use dynamic like below

var list = new List<dynamic>();
        list.Add(new {
            Name = "Damith"
    });
        foreach(var item in list){
            Console.WriteLine(item.Name);
        }
    }
Damith Asanka
  • 934
  • 10
  • 12
10

You can create a list of dynamic.

List<dynamic> anons=new List<dynamic>();
foreach (Model model in models)
{
   var anon= new
   {
      Id = model.Id,
      Name=model.Name
   };
   anons.Add(anon);
}

"dynamic" gets initialized by the first value added.

Code Name Jack
  • 2,856
  • 24
  • 40
8

Here is a another method of creating a List of anonymous types that allows you to start with an empty list, but still have access to IntelliSense.

var items = "".Select( t => new {Id = 1, Name = "foo"} ).ToList();

If you wanted to keep the first item, just put one letter in the string.

var items = "1".Select( t => new {Id = 1, Name = "foo"} ).ToList();
Brackus
  • 89
  • 1
  • 2
  • 1
    Using a string as a array initializer may work but is very bad practice – MikeT Nov 27 '14 at 10:52
  • I would say that most of the above answers are not particularly "good" practice, but that was kind of a given due to the nature of the question. Anonymous types were not really designed to work this way. I am curious though why my method is "worse" than the others? Something I'm missing? – Brackus Dec 15 '14 at 16:52
  • you are right as the question is asking for something that itself bad practice there can't be a good practice answer, but because you are using a string to generate an array of chars and then converting that into an array of what ever the user wants, which are unrelated types not to mention generating superfluous boxing and unboxing which is inefficient – MikeT Jan 05 '15 at 09:32
8

Here is my attempt.

List<object> list = new List<object> { new { Id = 10, Name = "Testing1" }, new {Id =2, Name ="Testing2" }}; 

I came up with this when I wrote something similar for making a Anonymous List for a custom type.

user_v
  • 9,628
  • 4
  • 40
  • 32
7

I'm very surprised nobody has suggested collection initializers. This way can only add objects when the list is created hence the name however it seems like the nicest way of doing it. No need to create an array then convert it to a list.

var list = new List<dynamic>() 
{ 
    new { Id = 1, Name = "Foo" }, 
    new { Id = 2, Name = "Bar" } 
};

You can always use object instead of dynamic but trying to keep it in a true generic way then dynamic makes more sense.

Tom Dee
  • 2,516
  • 4
  • 17
  • 25
  • dynamic and object are treated differently at runtime and compile time. If you try to call "list[0].Id" using dynamic you won't get compile errors. Using object is not possible. Object is the base class from which all classes are inherited, a predetermined "type". Dynamic, on the other hand, is an "undetermined type" before code execution. – tedebus Dec 10 '21 at 15:49
6

Instead of this:

var o = new { Id = 1, Name = "Foo" }; 
var o1 = new { Id = 2, Name = "Bar" }; 

List <var> list = new List<var>(); 
list.Add(o); 
list.Add(o1);

You could do this:

var o = new { Id = 1, Name = "Foo" }; 
var o1 = new { Id = 2, Name = "Bar" }; 

List<object> list = new List<object>(); 
list.Add(o); 
list.Add(o1);

However, you will get a compiletime error if you try to do something like this in another scope, although it works at runtime:

private List<object> GetList()
{ 
    List<object> list = new List<object>();
    var o = new { Id = 1, Name = "Foo" }; 
    var o1 = new { Id = 2, Name = "Bar" }; 
    list.Add(o); 
    list.Add(o1);
    return list;
}

private void WriteList()
{
    foreach (var item in GetList()) 
    { 
        Console.WriteLine("Name={0}{1}", item.Name, Environment.NewLine); 
    }
}

The problem is that only the members of Object are available at runtime, although intellisense will show the properties id and name.

In .net 4.0 a solution is to use the keyword dynamic istead of object in the code above.

Another solution is to use reflection to get the properties

using System;
using System.Collections.Generic;
using System.Reflection;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            var anonymous = p.GetList(new[]{
                new { Id = 1, Name = "Foo" },       
                new { Id = 2, Name = "Bar" }
            });

            p.WriteList(anonymous);
        }

        private List<T> GetList<T>(params T[] elements)
        {
            var a = TypeGenerator(elements);
            return a;
        }

        public static List<T> TypeGenerator<T>(T[] at)
        {
            return new List<T>(at);
        }

        private void WriteList<T>(List<T> elements)
        {
            PropertyInfo[] pi = typeof(T).GetProperties();
            foreach (var el in elements)
            {
                foreach (var p in pi)
                {
                    Console.WriteLine("{0}", p.GetValue(el, null));
                }
            }
            Console.ReadLine();
        }
    }
}
Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
Jakob Flygare
  • 77
  • 1
  • 1
5

This is an old question, but I thought I'd put in my C# 6 answer. I often have to set up test data that is easily entered in-code as a list of tuples. With a couple of extension functions, it is possible to have this nice, compact format, without repeating the names on each entry.

var people= new List<Tuple<int, int, string>>() {
    {1, 11, "Adam"},
    {2, 22, "Bill"},
    {3, 33, "Carol"}
}.Select(t => new { Id = t.Item1, Age = t.Item2, Name = t.Item3 });

This gives an IEnumerable - if you want a list that you can add to then just add ToList().

The magic comes from custom extension Add methods for tuples, as described at https://stackoverflow.com/a/27455822/4536527.

public static class TupleListExtensions    {
    public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
            T1 item1, T2 item2)       {
        list.Add(Tuple.Create(item1, item2));
    }

    public static void Add<T1, T2, T3>(this IList<Tuple<T1, T2, T3>> list,
            T1 item1, T2 item2, T3 item3) {
        list.Add(Tuple.Create(item1, item2, item3));
    }

// and so on...

}

The only thing I don't like is that the types are separated from the names, but if you really don't want to make a new class then this approach will still let you have readable data.

Community
  • 1
  • 1
Peter Davidson
  • 404
  • 4
  • 9
5

You can do it this way:

var o = new { Id = 1, Name = "Foo" };
var o1 = new { Id = 2, Name = "Bar" };

var array = new[] { o, o1 };
var list = array.ToList();

list.Add(new { Id = 3, Name = "Yeah" });

It seems a little "hacky" to me, but it works - if you really need to have a list and can't just use the anonymous array.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
Jermismo
  • 230
  • 4
  • 8
4

For your second example, where you have to initialize a new List<T>, one idea is to create an anonymous list, and then clear it.

var list = new[] { o, o1 }.ToList();
list.Clear();

//and you can keep adding.
while (....)
{
    ....
    list.Add(new { Id = x, Name = y });
    ....
}

Or as an extension method, should be easier:

public static List<T> GetEmptyListOfThisType<T>(this T item)
{
    return new List<T>();
}

//so you can call:
var list = new { Id = 0, Name = "" }.GetEmptyListOfThisType();

Or probably even shorter,

var list = new int[0].Select(x => new { Id = 0, Name = "" }).Tolist();
nawfal
  • 70,104
  • 56
  • 326
  • 368
4
var list = new[]{
new{
FirstField = default(string),
SecondField = default(int),
ThirdField = default(double)
}
}.ToList();
list.RemoveAt(0);
morlock
  • 49
  • 1
  • 1
1

Deriving from this answer, I came up with two methods that could do the task:

    /// <summary>
    /// Create a list of the given anonymous class. <paramref name="definition"/> isn't called, it is only used
    /// for the needed type inference. This overload is for when you don't have an instance of the anon class
    /// and don't want to make one to make the list.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="definition"></param>
    /// <returns></returns>
#pragma warning disable RECS0154 // Parameter is never used
    public static List<T> CreateListOfAnonType<T>(Func<T> definition)
#pragma warning restore RECS0154 // Parameter is never used
    {
        return new List<T>();
    }
    /// <summary>
    /// Create a list of the given anonymous class. <paramref name="definition"/> isn't added to the list, it is
    /// only used for the needed type inference. This overload is for when you do have an instance of the anon
    /// class and don't want the compiler to waste time making a temp class to define the type.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="definition"></param>
    /// <returns></returns>
#pragma warning disable RECS0154 // Parameter is never used
    public static List<T> CreateListOfAnonType<T>(T definition)
#pragma warning restore RECS0154 // Parameter is never used
    {
        return new List<T>();
    }

You can use the methods like

var emptyList = CreateListOfAnonType(()=>new { Id = default(int), Name = default(string) });
//or
var existingAnonInstance = new { Id = 59, Name = "Joe" };
var otherEmptyList = CreateListOfAnonType(existingAnonInstance);

This answer has a similar idea, but I didn't see it until after I made those methods.

BrainStorm.exe
  • 1,565
  • 3
  • 23
  • 40
0

Using Reflection

Microsoft documentation about this topic.

using System;
using System.Collections;
using System.Collections.Generic;

var anonObj = new { Id = 1, Name = "Foo" };
var anonType = anonObj.GetType();

var listType = typeof(List<>);

// We know that List<> have only one generic argument, so we do this:
var contructed = listType.MakeGenericType(anonType);

// Create instance
var instance = Activator.CreateInstance(contructed);

// Using it
var list = (IList)instance;
list.Add(anonObj);

For Dictionary<,> you need to pass 2 arguments
Ex.: dicType.MakeGenericType( type1, type2 )

And for generic types with constraints (where T : struct), we need to do more verifications. Check microsoft docs to learn how.

Henryk Budzinski
  • 1,161
  • 8
  • 20
-2

Try with this:

var result = new List<object>();

foreach (var test in model.ToList()) {
   result.Add(new {Id = test.IdSoc,Nom = test.Nom});
}
Matteo Gariglio
  • 482
  • 5
  • 12