Anonymous type collections?

16,614

Solution 1

For a very different answer... LINQ?

In my case, I am iterating over a collection - for each item in the collection I would like to collect related objects in an anonymous type (acting as a tuple). I need these anonymous types to be put in a collection and then sort them for further work.

That sounds like:

var list = (from item in collection
          from related in item.Relationship
          order by ...something...
          select new {item,related}).ToList()

Solution 2

If you're happy with an array, you can use an array initializer:

var items = new[] {
    new { Foo = "def" },
    new { Foo = "ghi" },
    new { Foo = "jkl" }
};

You can then call ToList() if you want to get a List<T> out. Marc's solution will be slightly more efficient than calling ToList() due to not needing the extra copying, but I think I'd probably use the "array and then ToList()" solution in most cases as there's less clutter. Of course, if performance is crucial for that bit of code, it changes things.

EDIT: As you're iterating over a collection, just use Select:

var anonymousItems = items.Select (item => new { Foo=item.Foo, 
                                                 Bar=item.Other })
                          .ToList();

Solution 3

One option is to use an example item to create the collection via generic type inference, for example:

    static List<T> CreateEmptyList<T>(T template) {
        return new List<T>();
    }
    void Foo() {
        var list = CreateEmptyList(new { Foo = "abc" });
        list.Add(new { Foo = "def" });
        //...
    }

You can also do this without creating an instance (but using an anonymous method that never gets caller), but I don't think it saves anything really... we might not create an instance of the object, but we do create an instance of a delegate, so not much of a saving...

You also mention sorting the data; see the reply here for a way to use List<T>.Sort with a lambda, and hence with anonymous types - i.e.

list.Sort(x=>x.Foo);

Solution 4

LINQ is the way to go. Assuming you want to fetch the related objects A, B and C of every item in a collection items and sort by the related object A you would go as follows.

var relatedObjects = items.
       Select(item => new { A = item.A, B = item.B, C = item.C } ).
       OrderBy(item => item.A);

You get a collection of items of an anonymous type with the three properties A, B and C set to the related objects ordered by the related object A.

I did not verify that, but you should be able to extend the relatedObject collection later. Just do the following to add a single new item. This should work because there is only one anonymous type per assembly I think if the names and types of each property match.

relatedObjects = relatedObjects.Union(
   Enumerable.Repeat(new { A = someA, B = someB, C = someC }, 1))

Quite ugly because of the Enumerable.Repeat() but becomes quite nice if you union with a collection of new items instead of a single new item.

Solution 5

I stumbled upon this question while looking for a way to create a temporary list of temporary objects. Why would I want to create such a thing? I was looking for a quick way to return JSON for a list of objects made from some values of another object. Here's what I mean.

Suppose I have an Employee class on the server side which looks like the following in C#:

public class Employee
{
          public int Id;
       public int businessGroupId;
       public string title;
       public int positionId;

       public string firstName;
       public string lastName;
       ...
}

Furthermore I have a collection of those objects which I can easily iterate through, something like the following:

List<Employee> allEmployees  = new List<Employee>();

Now, I want to return to my calling web page the entire collection of Employees, but I only want the firstName, lastName for each. I want them returned as JSON.

Here's The Important Point

I do not want to return every property in the Employee Object.

I know I can easily create an anonymous type by iterating through the allEmployees collection and building a new object each time.

It would look something like the following:

foreach (Employee e in allEmployees)
{
    var tempObj = new {F_Name=e.firstName, L_Name=e.lastName};
}

What's The Type Of An Anonymous Type? :)

The trick now is that I want an entire collection (List<>)of these anonymous objects. However, I have no way to provide the List a type that I will be using. I cannot create a List<unknown> allTempObjects = new List<unknown>();

Or can I?

With dynamic, It Is Possible

I can do the following and it works great:

List<dynamic> allEmployees  = new List<dynamic>();

foreach (Employee e in allEmployees)
{
           var tempObj = new {F_Name=e.firstName, L_Name=e.lastName};
        allEmployees.Add(tempObj);
}

// use the JavaScript Serializer to serialize the dynamic collection
JavaScriptSerializer jss = new JavaScriptSerializer();
// write the result out to the HTTP Stream (HtmlTextWriter in overridden Render method)

 writer.Write(jss.Serialize(allEmployees));

You will see JSON on the client side which looks like the following:

[
    {
      F_Name: "Seth",
      L_Name: "Godin"
    },
    {
       F_Name: "Charles",
       L_Name: "Petzold"
    },
    {
       F_Name: "Jeff",
       L_Name: "Prosise"
    }
]

Finally, you may question why I want to do this. The simple answer is that I want to new type which is only used to serialize to send to my client. A great reason for an anonymous type and an anonymous collection of anonymous types, don't you think?

Share:
16,614
Oded
Author by

Oded

Former Stack Overflow employee. I am a C# ASP.NET developer, with a long professional history of work with web and Microsoft technologies. I am passionate about writing usable and secure software and am constantly learning. Blog at http://OdedCoster.com/blog. I have written a blog series about getting good answers on StackOverflow.

Updated on June 04, 2022

Comments

  • Oded
    Oded almost 2 years

    I am looking for best practices for creating collections made from anonymous types.

    There are several approaches - this one and most answers on this thread assume that the whole anonymous collection can be constructed in one statement.

    As anonymous types are usually used to replace classes that are to be used to store temporary (as put forward in this SO answer), I would like to avoid creating and using a class for anonymous collections, as this post suggests.

    In my case, I am iterating over a collection - for each item in the collection I would like to collect related objects in an anonymous type (acting as a tuple). I need these anonymous types to be put in a collection and then sort them for further work.

    Other approaches I have considered:

    1. Use an object[] or ArrayList (losing the benefit of the anonymous type)
    2. Creating a wrapper class for the required items (removing the need for the anonymous type)

    This is the only place in my code that I need such a collection - what would be the best approach?

    Additional Information:

    I am working with legacy .Net 1.1 objects, so the collections I am working with are strongly typed collections implementing IEnumerable, and as such most Linq extension methods such as .Select won't work:

    Code sample

    foreach (Item item in myItems)
    {
        foreach (Confirmation confirmation in item.GetConfirmations(true))
        {
            if (lastParentId != item.ParentId)
            {
                lastParentId = item.ParentId;
                parentObject = new ParentItem(lastParentId);
            }
    
            itemHolder = new ArrayList { item, confirmation };
            if (parentObject!= null)
            {
                itemHolder.Add(parentObject.Rate);
            }
    
            sortConfirmations.Add(confirmation.Date, itemHolder);
        }
    }
    
    // Use sortConfirmations
    

    Resolution

    I ended up using a generic dictionary to collect the related items together and using .OrderBy() to sort them - ugly, but it works... and is better than the existing code.

  • Oded
    Oded about 15 years
    Can't do that, as I am iterating over an existing collection to retrieve the objects I want to put into the anonymouse type. I was meaning to do collection.Add(anonType).
  • Oded
    Oded about 15 years
    Unfortunately I need to new up some of the objects I will be collecting in the anonymous type. I am converting some existing code that is putting these objects in an ArrayList and each array list into a SorteList. I need to achieve something similar, but cleaner.
  • Marc Gravell
    Marc Gravell about 15 years
    @Oded - that is often still possible. Of course, it is hard to say for sure without a concrete example...
  • Guffa
    Guffa about 15 years
    @Marc Gravell: Yes, of course, you would need something like a List<object> to handle both types, losing the direct connection to the anonymous type information.
  • Jon Skeet
    Jon Skeet about 15 years
    +1 for the "we need more information" point. I strongly suspect that LINQ is the way forward here.
  • STW
    STW over 12 years
    A small tip: arrays are readonly, so if using this method consider calling .ToList() to produce a writable collection. This is very handy in unit test scenarios for things such as extention methods.
  • Topman
    Topman about 7 years
    It helped. Thanks