A generic list of anonymous class

C#.NetGenericsAnonymous Types

C# Problem Overview


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});
    ....
}

C# Solutions


Solution 1 - C#

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

Solution 2 - C#

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

Solution 3 - C#

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();   

Solution 4 - C#

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.

Solution 5 - C#

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.

Solution 6 - C#

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 });
}

Solution 7 - C#

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"));

Solution 8 - C#

You can do this in your code.

var list = new[] { new { Id = 1, Name = "Foo" } }.ToList();
list.Add(new { Id = 2, Name = "Bar" });

Solution 9 - C#

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);
        }
    }

Solution 10 - C#

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();

Solution 11 - C#

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.

Solution 12 - C#

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.

Solution 13 - C#

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();

Solution 14 - C#

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.

Solution 15 - C#

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();
        }
    }
}

Solution 16 - C#

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.

Solution 17 - C#

var list = new[]{
new{
FirstField = default(string),
SecondField = default(int),
ThirdField = default(double)
}
}.ToList();
list.RemoveAt(0);

Solution 18 - C#

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.

Solution 19 - C#

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();

Solution 20 - C#

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.

Solution 21 - C#

Try with this:

var result = new List<object>();

foreach (var test in model.ToList()) {
   result.Add(new {Id = test.IdSoc,Nom = test.Nom});
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDHornpoutView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#DuttView Answer on Stackoverflow
Solution 3 - C#Paul RouleauView Answer on Stackoverflow
Solution 4 - C#Jeff MoserView Answer on Stackoverflow
Solution 5 - C#RostovView Answer on Stackoverflow
Solution 6 - C#erikkallenView Answer on Stackoverflow
Solution 7 - C#BassemView Answer on Stackoverflow
Solution 8 - C#MalachiteBRView Answer on Stackoverflow
Solution 9 - C#Damith AsankaView Answer on Stackoverflow
Solution 10 - C#MECView Answer on Stackoverflow
Solution 11 - C#Code Name JackView Answer on Stackoverflow
Solution 12 - C#user_vView Answer on Stackoverflow
Solution 13 - C#BrackusView Answer on Stackoverflow
Solution 14 - C#Tom DeeView Answer on Stackoverflow
Solution 15 - C#Jakob FlygareView Answer on Stackoverflow
Solution 16 - C#JermismoView Answer on Stackoverflow
Solution 17 - C#morlockView Answer on Stackoverflow
Solution 18 - C#Peter DavidsonView Answer on Stackoverflow
Solution 19 - C#nawfalView Answer on Stackoverflow
Solution 20 - C#BrainStorm.exeView Answer on Stackoverflow
Solution 21 - C#Matteo GariglioView Answer on Stackoverflow