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


Анонимные типы

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

Анонимные типы создаются с помощью new оператора вместе с инициализатором объектов. Дополнительные сведения об инициализаторах объектов см. в статье Инициализаторы объектов и коллекций.

В следующем примере показан анонимный тип, инициализированный с помощью двух свойств — Amount и Message.

var v = new { Amount = 108, Message = "Hello" };

// Rest the mouse pointer over v.Amount and v.Message in the following
// statement to verify that their inferred types are int and string.
Console.WriteLine(v.Amount + v.Message);

Анонимные типы обычно используются в select предложении выражения запроса для возврата подмножества свойств из каждого объекта в исходной последовательности. Дополнительные сведения о запросах см. в разделе о LINQ в C#.

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

Наиболее частый сценарий — это инициализация анонимного типа со свойствами из другого типа. В следующем примере предполагается, что существует класс с именем Product. Класс Product включает Color и Price свойства вместе с другими свойствами, которые вам не нужны:

class Product
{
    public string? Color {get;set;}
    public  decimal Price {get;set;}
    public string? Name {get;set;}
    public string? Category {get;set;}
    public string? Size {get;set;}
}

Объявление анонимного типа запускается с помощью ключевого слова new. Объявление инициализирует новый тип, который использует только два свойства из Product. Использование анонимных типов приводит к тому, что в запросе возвращается меньший объем данных.

Если имена членов в анонимном типе не указаны, компилятор предоставляет членам анонимного типа то же имя, что и свойство, используемое для инициализации. Укажите имя свойства, инициализируемого выражением, как показано в предыдущем примере. В следующем примере используются имена свойств анонимного типа Color и Price. Экземпляры являются элементами Product из products коллекции типов:

var productQuery =
    from prod in products
    select new { prod.Color, prod.Price };

foreach (var v in productQuery)
{
    Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}

Совет

Правило стиля .NET можно использовать IDE0037 для принудительного применения выводимых или явных имен элементов.

Также можно определить поле по объекту другого типа: класс, структуру или даже другой анонимный тип. Это делается с помощью переменной, удерживающей этот объект так же, как в следующем примере, где создаются два анонимных типа с использованием уже созданных пользователем типов. В обоих случаях product поле в анонимном типе shipment и shipmentWithBonus будет иметь тип Product , содержащий значения по умолчанию каждого поля. bonus И поле будет иметь анонимный тип, созданный компилятором.

var product = new Product();
var bonus = new { note = "You won!" };
var shipment = new { address = "Nowhere St.", product };
var shipmentWithBonus = new { address = "Somewhere St.", product, bonus };

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

Вы можете создать массив анонимно типизированных элементов, объединив неявно типизированные локальные переменные и неявно типизированный массив, как показано в следующем примере.

var anonArray = new[] { new { name = "apple", diam = 4 }, new { name = "grape", diam = 1 }};

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

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

Анонимные типы поддерживают неразрушительную мутацию в виде выражений. Это позволяет создать новый экземпляр анонимного типа, где одно или несколько свойств имеют новые значения:

var apple = new { Item = "apples", Price = 1.35 };
var onSale = apple with { Price = 0.79 };
Console.WriteLine(apple);
Console.WriteLine(onSale);

Никакое поле, свойство, событие или тип возвращаемого значения метода невозможно объявить, используя анонимный тип. Точно так же нельзя объявить с помощью анонимного типа ни один формальный параметр метода, свойства, конструктора или индексатора. Чтобы передать анонимный тип или коллекцию, содержащую анонимные типы, в качестве аргумента в метод, можно объявить параметр как тип object. Однако использование object для анонимных типов побеждает цель строгого ввода. Если вам нужно сохранить результаты запроса или передать их за пределы метода, используйте вместо анонимного типа структуру или класс, названные обычным образом.

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

Примечание.

Уровень доступности анонимного типа , internalпоэтому два анонимных типа, определенных в разных сборках, не имеют одного типа. Таким образом, экземпляры анонимных типов не могут быть равны друг другу при определении в разных сборках, даже если все их свойства равны.

Анонимные типы переопределяют ToString метод, сцепляя имя и ToString выходные данные каждого свойства, окруженного фигурными скобками.

var v = new { Title = "Hello", Age = 24 };

Console.WriteLine(v.ToString()); // "{ Title = Hello, Age = 24 }"