Skip to content

Anonymous types C# 3.0code reduction

Simple data containers for internal operations.

Tuples are popular choices in other programming languages for tightly-scoped data containers. One drawbacks of tuples is that items within the tuple are referenced by a numerical position rather than a name much like an array.

Anonymous types give some of the convenience of tuples but with the ability to name the items contained within it. The trade-offs are that each anonymous type is independent and is not interchangeable with other types even when they have an identical definition and that the type has no name you can refer to directly (but you can indirectly using generics).3

Code

C#
var contacts = db.Customers.Select(c => new { c.Name, c.Email });

foreach (var contact in contacts)
    Console.WriteLine(contact.Name + "\t" + contact.Email);
C#
var contacts = db.Customers.Select(c => new Contact { Name = c.Name, Email = c.Email });

foreach (var contact in contacts)
    Console.WriteLine(contact.Name + "\t" + contact.Email);

// ...

class Contact
{
    string Name;
    string Email;
}

Notes

  • The compiler will create a class named <>c and put your anonymous method there
  • Anonymous types are often used in LINQ Select statements to "project" a final structure:
    • Recommended for LINQ with databases to reduce overhead on the database server and network1 2
    • Discouraged for LINQ to Objects (in-memory collections like List<T>) as it uses extra memory
    • Might still be worth it if the project forms an external API contract such as in a JSON API

1 LINQ providers only understand the query and the lambda expressions. Using this kind of projection tells them what fields they need to retrieve (they can not look at other code as it is compiled).

2 You can project into other classes but really only as the last operation in the query. Some providers can follow the assignment through other classes mid-query if you use initializer syntax but many do not. Using a constructor mid-query will almost certainly fail or result in wrong behavior.

3 If you want that behavior you can always use Tuple.Create which share types between identical structures at the expense of giving up names for Item1, Item2 etc. Alternatively you can make your method generic and have the parameter be the generic type - the runtime will take care of ensuring the method is created with the correct anonymous declaration.

More information