What are Anonymous Types in C#

Anonymous types are a mighty instrument in object-oriented programming disciplines. In strongly typed programming languages like C#, we need to always define the type of a variable before we can create new ones. Sometimes we have to create a new instance of an object with an unknown type and read-only attributes, which can be done only with explicitly undefined types.

By clearly describing small things, they can encapsulate attributes into an object without defining a type. And every single object can hold any combination of attributes, regardless of their data type, as long as each attribute is clearly defined and described.

They are perfect for the execution of SQL-like LINQ because they return an unspecified type to define the new object on the fly. It can help you streamline your C# and .NET code while also providing developers with a powerful tool for creating unidentified anonymous objects with a predefined structure.

How to Use Anonymous Types

Anonymous typing simplifies development and produces more readable and clean code. In combination with generics, you can create strongly typed collections, which can be useful with LINQ queries, passing attributes, or creating models in ASP.NET MVC.

Anonymous typing doesn’t work with inheritance or interface implementation. If you need a more complex type that requires functions or fields, your best choice is to define a class.

C# Anonymous Types Example

We made an array called “hackers” that has two objects in it with the values “Type” and “Exp“, a list called uniqueHackers, and a hash set called seenTypes.

The code iterates through the hackers array, and for each unique type, finds the maximum experience among all hackers. Finally, it creates a new object with a unique type and maximum experience and adds it to the uniqueHackers list.

This code will find the hacker(s) with the highest experience for each type of hacker. Note that it is a list of anonymous types, so you won’t be able to access the properties directly by name. Instead, you can use reflection or dynamic typing to access the attributes.

var hackers = new[] {
  new { Type = "Anonymous", Exp = 3 },
  new { Type = "Anonymous", Exp = 5 }
};
var uniqueHackers = new List<object>();
var seenTypes = new HashSet<string>();
foreach (var person in hackers) {
  if (!seenTypes.Contains(person.Type)) {
    seenTypes.Add(person.Type);
    var maxExp = person.Exp;
    foreach (var otherPerson in hackers) {
      if (person.Type == otherPerson.Type &&
otherPerson.Exp > maxExp) {
        maxExp = otherPerson.Exp;
      }
    }
    uniqueHackers.Add(new { Type = person.Type,
Exp = maxExp });
  }
}

Nested Anonymous Type in C#

Anonymous types can’t be used outside of the scope where they are defined, so they may not be suitable for more complex scenarios or for sharing data across multiple methods or classes.

This code is more concise and easier to read, especially when dealing with simple data structures. Here’s a code example of how you could create a nested anonymous type from the people array in the original code. It’s important to note that code readability can suffer if there are too many nested levels. In such cases, it may be preferable to utilize named types or nested classes instead.

var hackers = new[] {
  new {
    Type = "Anonymous",
    Exp = 3,
    Address = new {
      Street = "123 Main St",
      City = "Anytown",
      State = "CA",
      ZipCode = "12345"
    }
  },
  new {
    Type = "Anonymous",
    Exp = 5,
    Address = new {
      Street = "456 Elm St",
      City = "Sometown",
      State = "CA",
      ZipCode = "67890"
    }
  }
};

In this code example, the people array contains two objects, each with Type, Exp, and Address, which itself is an anonymous object with Street, City, State, and ZipCode properties. When dealing with complex data structures, we can utilize dot notation to access the nested properties like this:

Console.WriteLine(hackers[0].Type); 
// Output: Anonymous
Console.WriteLine(hackers[0].Address.Street); 
// Output: 123 Main St
Console.WriteLine(hackers[1].Address.City); 
// Output: Sometown

Anonymous Types in LINQ

LINQ can significantly simplify the code and enhance its readability when you work with complex data structures. To create an anonymous array using a LINQ query, modify the code as follows:

This snippet creates a new anonymousArray with Type and Exp properties. This code uses LINQ to sort by maximum experience, then creates an array with unique hackers, similar to the original code. There we have concise and readable code while still achieving the desired functionality.

Note that the order of the elements in uniqueHackers is not guaranteed, so we set the properties of each element in anonymousArray explicitly to ensure they match the original hackers array.

var hackers = new[] {
  new { Type = "Anonymous", Exp = 3 },
  new { Type = "Anonymous", Exp = 5 }
};
var uniqueHackers = hackers
  .GroupBy(h => h.Type)
  .Select(g => new { Type = g.Key, Exp =
g.Max(h => h.Exp) })
  .ToArray();
var anonymousArray = new[] {
  new { Type = uniqueHackers[0].Type, Exp =
uniqueHackers[0].Exp },
  new { Type = uniqueHackers[1].Type, Exp =
uniqueHackers[1].Exp }
};