In this article, we’re going to learn about anonymous types in C#. After learning what they are, we’re going to learn how to use them in various scenarios through examples.

To download the source code for this article, you can visit our GitHub repository.

Let’s dive in.

What Are Anonymous Types in C#?

Anonymous types are class-level reference types that don’t have a name. They allow us to instantiate an object without explicitly defining a type.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

They contain one or more read-only properties. The compiler determines the type of the properties based on the assigned values. It also generates a name for the object’s type since it’s unknown.

A common usage of anonymous types is local temporary data storage. Instead of assigning entire objects to anonymous types, we assign only the specific properties of other objects that we need. This is also useful when working with LINQ expressions.

How to Use Anonymous Types?

Anonymous types must be defined using an object initializer along with the var and new keywords. The properties can’t contain null values, class methods, or events. The properties also can’t change.

We can define an anonymous type:

var employee = new
{
    Id = 001,
    FirstName = "John",
    LastName = "Doe",
    Department = "Marketing",
    FullTime = false,
    HourlyPay = 35.75
};

Console.WriteLine($"Id: {employee.Id}");                  // Id: 1
Console.WriteLine($"First Name: {employee.FirstName}");   // First Name: John  
Console.WriteLine($"Last Name: {employee.LastName}");     // Last Name: Doe
Console.WriteLine($"Department: {employee.Department}");  // Department: Marketing
Console.WriteLine($"Full Time: {employee.FullTime}");     // Full Time: False
Console.WriteLine($"Hourly Pay: {employee.HourlyPay}");   // Hourly Pay: 35.75

As you can see we can access the properties the same way we would do it if it was a regular object.

Since the compiler determines the type, we can use the Object.GetType() method to get the type that was determined:

Console.WriteLine($"Id Type: {employee.Id.GetType()}");                  // Id Type: int
Console.WriteLine($"First Name Type: {employee.FirstName.GetType()}");   // First Name Type: string
Console.WriteLine($"Last Name Type: {employee.LastName.GetType()}");     // Last Name Type: string
Console.WriteLine($"Department Type: {employee.Department.GetType()}");  // Department Type: string
Console.WriteLine($"Full Time Type: {employee.FullTime.GetType()}");     // Full Time Type: bool
Console.WriteLine($"Hourly Pay Type: {employee.HourlyPay.GetType()}");   // Hourly Pay Type: double

Nested Anonymous Types

We can nest anonymous types within the properties of an anonymous type:

var employee = new
{
    Id = 0002,
    FirstName = "Jane",
    LastName = "Doe",
    Department = "Accounting",
    OfficeAddress = new { Street = "123 Green St.", 
                          City = "Atlanta", 
                          State = "Georgia", 
                          Country = "USA" }
};

Console.WriteLine($"Employee Office Location: {employee.OfficeAddress.City}");  // Employee Office Location: Atlanta

Array of Anonymous Types

We can also store anonymous types inside of an array:

var employees = new[]
{
    new { Id = 001, FirstName = "John", LastName = "Doe", Department = "Marketing" },
    new { Id = 002, FirstName = "Jane", LastName = "Doe", Department = "Accounting" },
    new { Id = 003, FirstName = "Bob", LastName = "Smith", Department = "Human Resources" }
};

We can iterate or perform other operations with the list of anonymous objects as usual:

foreach (var emp in employees)
{
    Console.WriteLine($"Id: {emp.Id} Name: {emp.FirstName} {emp.LastName}");
}

// Id: 1 Name: John Doe
// Id: 2 Name: Jane Doe
// Id: 3 Name: Bob Smith

Anonymous Types in LINQ Expressions

As mentioned earlier, anonymous types are useful in LINQ expressions because we can get only the values from the properties we need. This helps save memory and avoid unnecessary code:

var employeesFromList = from e in EmployeeList
               select new { Id = e.Id, Name = $"{e.FirstName} {e.LastName}" };

foreach (var emp in employeesFromList)
    Console.WriteLine($"Id: {emp.Id} Name: {emp.Name}");

Anonymous vs Dynamic Types

Anonymous types and dynamic types are very alike. They are both similarly defined except dynamic types use the dynamic keyword:

dynamic employee = new
{
    Id = 001,
    FirstName = "John",
    LastName = "Doe",
};

At the first glance they look the same:

Console.WriteLine($"Id: {employee.Id}");                               // Id: 1
Console.WriteLine($"Name: {employee.FirstName} {employee.LastName}");  // Name: John Doe

The key difference is the compiler checks anonymous types, while the runtime checks dynamic types.

If we attempt to change a property of an anonymous object, the code will not compile. If we attempt to change a property of a dynamic object, an error will occur at runtime.

Anonymous Type Limitations

Anonymous types have a few limitations we should consider when using them. They can only contain public, read-only properties so they can’t have fields, events, or methods.

Once an anonymous type has been initialized, we can’t add properties or change the values of the existing ones. We also can’t create a field, property, event, or return type of a method as an anonymous type.

Conclusion

In this article, we defined what anonymous types are and their uses. We’ve learned how to use anonymous types in a general sense, how to nest them, how to assign them to an array, and how to use them with LINQ expressions. We’ve also learned the difference between anonymous types and dynamic types.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!