C# Anonymous Types

Summary: in this tutorial, you’ll learn about C# anonymous types to create a single object that consists of read-only properties without having to define a class first.

Introduction to C# anonymous types

Typically, you define a class that has a set of properties and use the class to create objects.

But sometimes you need to create an object that has a set of read-only properties without having to define a class. To do it, you use anonymous types.

By definition, anonymous types allow you to encapsulate a set of read-only properties into a single object without having to define a class first.

Behind the scenes, the compiler will generate the type name for the anonymous type. Therefore, the type name is not accessible at the source code level. The compiler also infers the type of each property of the anonymous type.

To create anonymous types, you use the new operator with an object initializer. For example, the following demonstrates how to create an anonymous type with two properties named Name and Price:

using static System.Console;

var product = new
{
    Name = "Phone X",
    Price = 999.99
};

WriteLine($"{product.Name} : {product.Price:C}");Code language: C# (cs)

Output:

Phone X : $999.99Code language: C# (cs)

If you hover the mouse over the Name or Price properties, you’ll see that the compiler infers the type of the Name property to string and the type of the Price property to double:

c# anonymous types

Because the Name and Price properties are read-only, if you attempt to assign a new value to it, you’ll get a compiled error. For example:

product.Price = 2000; // errorCode language: C# (cs)

To form a new anonymous object with the same name and different price, you can use the with expression.

The with expression creates an anonymous type object where one or more properties have new values. For example:

using static System.Console;

var product = new
{
    Name = "Phone X",
    Price = 999.99
};
WriteLine($"{product.Name} : {product.Price:C}");


var productX = product with
{
    Price = 1099.99
};
WriteLine($"{productX.Name} : {productX.Price:C}");
Code language: C# (cs)

Output:

Phone X : $999.99
Phone X : $1,099.99Code language: C# (cs)

In this example, we use the with expression to create a new instance of the same anonymous type with the product object, but with the new Price value.

It’s possible to define an array of anonymous types like this:

var products = new[]
{
    new { Name = "Phone X", Price = 999.99 },
    new { Name = "Computer Y", Price = 1999.99 },
    new { Name = "Tablet Z", Price = 2999.99 }
};Code language: C# (cs)

And an anonymous type can have properties that are instances of explicit types. For example:

using static System.Console;


var product = new
{
    Name = "Phone X",
    Price = 999.99,
    attribute = new ProductAttribute() { Color = "Black", Weight = 100 }
};

WriteLine($"{product.Name}: {product.attribute.Color}");



class ProductAttribute
{
    public string? Color
    {
        get; init;
    }
    public decimal? Weight
    {
        get; init;
    }
}Code language: C# (cs)

In this example, we define an anonymous object with a property that is an instance of the ProductAttribute class.

The supertype of anonymous types

Anonymous types inherit directly from the object type. And you cannot cast anonymous types to any type except object.

If you have two or more anonymous objects that have the same set of properties in the same order and types, the compiler will treat these objects with the same type. In other words, they share the same generated type. For example:

using static System.Console;

var productX = new { Name = "Phone X", Price = 999.99 };
var productY = new { Name = "Phone Y", Price = 555.99 };

WriteLine(productX.GetType() == productY.GetType()); // trueCode language: C# (cs)

Output:

<>f__AnonymousType0`2[System.String,System.Double]
TrueCode language: C# (cs)

In this example, productX and productY will share the same anonymous type’s name. Note that you may get a different generated type name.

Two anonymous objects of the same type are equal if all their properties are equal. For example:

using static System.Console;

var productX = new { Name = "Phone X", Price = 99 };
var productY = new { Name = "Phone X", Price = 99 };

WriteLine(productX.Equals(productY));Code language: C# (cs)

Output:

TrueCode language: C# (cs)

The reason is that anonymous types override the Equals and GetHashCode methods in terms of Equals and GetHashCode methods of its properties.

Anonymous types override the ToString method by concatenating the results of ToString method of all properties and wrapping it in curly braces:

using static System.Console;

var productX = new { Name = "Phone X", Price = 99 };

WriteLine(productX.ToString());Code language: C# (cs)

Output:

using static System.Console;

var productX = new { Name = "Phone X", Price = 99 };

WriteLine(productX.ToString());Code language: C# (cs)

Output:

{ Name = Phone X, Price = 99 }Code language: C# (cs)

Summary

  • Use anonymous types to create an object with read-only properties.
  • Use the new keyword and an object initializer to declare an anonymous type.
  • Use anonymous types when you want to create an object that stores data temporarily without defining a separate type.
  • Anonymous types are immutable, implicitly typed, and created at runtime.
Was this tutorial helpful ?