Skip to content

Anonymous types C# 3.0code reduction

Create objects without explicitly defining a type.

Tuples are popular choices in other programming languages for tightly-scoped data containers. One drawback 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 an anonymous type is not interchangeable with named types or with anonymous types from other assemblies (within one assembly, the same property names and types in the same order share one type) and that the type has no name you can refer to directly (but you can indirectly using generics).3

Code ​

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

foreach (var contact in contacts)
    Console.WriteLine(contact.Name + "\t" + contact.Email);
csharp
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
{
    public string Name { get; set; }
    public string Email { get; set; }
}

Notes ​

  • The compiler will create a class named <>f__AnonymousType0 (and so on) for each anonymous type
  • Anonymous type properties are read-only, and the compiler generates value-based Equals, GetHashCode and ToString
  • 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 to share a type across methods or assemblies you can use Tuple.Create (.NET 4), at the expense of giving up names for Item1, Item2 etc., or Tuples C# 7.0 which keep the names. 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 ​

Powered by Intracia