Поделиться через


Анонимные типы (руководство по программированию на C#)

Анонимные типы предоставляют удобный способ инкапсулировать набор свойств только для чтения в один объект без определения именованного типа. Компилятор создает имя типа во время компиляции, которое невозможно получить в исходном коде. Компилятор определяет тип каждого свойства.

Создайте анонимные типы с помощью new оператора вместе с инициализатором объектов. В следующем примере показан анонимный тип, инициализируемый двумя свойствами, Name и Age:

var person = new { Name = "Alice", Age = 30 };
Console.WriteLine($"{person.Name} is {person.Age} years old.");
// Output:
// Alice is 30 years old.

Выводимые имена свойств

Имена свойств можно указать явным образом с помощью синтаксиса Name = value . При инициализации анонимного типа через выражение доступа к элементу или переменной, компилятор определяет имя свойства на основе этого выражения:

string productName = "Laptop";
decimal price = 999.99m;
var product = new { productName, price };
Console.WriteLine($"{product.productName}: {product.price:C}");
// Output:
// Laptop: $999.99

В приведенном выше примере компилятор выводит productName и price в качестве имен свойств из имен переменных, используемых в инициализаторе.

Объявление анонимных типов с помощью var

Так как компилятор создает имя типа и не может получить доступ к нему в исходном коде, необходимо использовать var для объявления локальной переменной. Невозможно явно указать имя типа:

// You must use var — you can't write a named type here.
var person = new { Name = "Alice", Age = 30 };

Использование анонимных типов в запросах LINQ

Анонимные типы чаще всего отображаются в select предложении выражения запроса, где они проектируют подмножество свойств из каждого исходного элемента:

var words = new[] { "apple", "blueberry", "cherry" };

var results = words.Select(w => new { Word = w, Length = w.Length });

foreach (var item in results)
{
    Console.WriteLine($"{item.Word} has {item.Length} letters.");
}
// Output:
// apple has 5 letters.
// blueberry has 9 letters.
// cherry has 6 letters.

Равенство

Два экземпляра анонимного типа с одинаковыми именами свойств и типами в одном порядке используют один и тот же тип, созданный компилятором. Компилятор переопределяет Equals, так что GetHashCode сравнивает значения свойств, а не идентичность ссылки.

var a = new { Name = "Alice", Age = 30 };
var b = new { Name = "Alice", Age = 30 };
var c = new { Name = "Bob", Age = 25 };

Console.WriteLine(a.Equals(b));  // True
Console.WriteLine(a.Equals(c));  // False

Вложенные анонимные типы

Анонимные типы могут содержать другие анонимные типы в качестве значений свойств:

var order = new
{
    OrderId = 1,
    Customer = new { Name = "Alice", City = "Seattle" },
    Total = 150.00m
};
Console.WriteLine($"Order {order.OrderId} for {order.Customer.Name} in {order.Customer.City}");
// Output:
// Order 1 for Alice in Seattle

Характеристики

Анонимные типы имеют следующие характеристики:

  • Компилятор создает их как internal sealed class типы, производные от Object.
  • Все свойства доступны public только для чтения.
  • Анонимные типы поддерживают with выражения для недеструктивной мутации.
  • Компилятор генерирует переопределения для значений Equals, GetHashCode и ToString.
  • Анонимные типы поддерживают деревья выражений, в то время как кортежи не поддерживаются.

Ограничения

Анонимные типы имеют несколько ограничений:

  • Их нельзя использовать в качестве типов возвращаемых методов, параметров метода или типов полей, так как не удается назвать тип.
  • Они ограничены тем методом, в котором вы их объявляете.
  • Нельзя добавлять методы, события или пользовательские операторы.
  • Свойства всегда доступны только для чтения; анонимные типы не поддерживают изменяемые свойства.

Когда вместо этого следует использовать кортежи

Для большинства новых кодов рекомендуется использовать кортежи вместо анонимных типов. Кортежи, являясь типами значений, обеспечивают лучшую производительность. Они также обеспечивают поддержку деконструкции и более гибкий синтаксис. Анонимные типы остаются лучшим выбором, если требуется поддержка дерева выражений или семантика ссылочного типа. Подробное сравнение см. в Выбор между анонимными и кортежными типами.

См. также