# 000169. Анонимные и динамические типы в c\#

Анонимные и динамические типы в c#||wmysterio|wmysterio|<wmysterio@yandex.ru>|/||Всем невероятный привет! ![smile](http://s49.ucoz.net/sm/15/smile.gif) С Вами, как всегда, wmysterio, и сегодня я расскажу очередную интересную информацию о C#. Из заголовка статьи, некоторые уже догадались о чём будет идти речь, но я решил поделится со всеми желающими этими возможностями.\
Начну этот рассказ с динамических типов, вернее сказать типом. Его суть в том, что переменная в классе или структуре может иметь "плавающий" тип. Другими словами менять свой тип в ходе выполнения программы. Для знакомства с темами урока, давайте создадим новый проект консольного приложения. Для экспериментов создадим класс "DynamicClass" с пустым конструктором:

Кодusing System;\
\
namespace test {\
\
&#x20; class Program {\
\
&#x20; static void Main( string\[] args ) {\
\
&#x20; }\
\
&#x20; }\
\
&#x20; // Наш новый класс\
&#x20; public class DynamicClass {\
\
&#x20; public DynamicClass() { }\
&#x20;  \
&#x20; }\
\
}Теперь нужно добавить новое слово в наш шарп-лексику - **dynamic**. Давайте добавим в Наш класс поле с именем "Field", и укажем в конструкторе, что оно по-умолчанию равно нулю:Код// Наш новый класс\
public class DynamicClass {\
\
&#x20; public dynamic Field; // Наше динамическое поле\
\
&#x20; public DynamicClass() { Field = 0; }\
&#x20;  \
}Теперь делаем тесты в функции Main. Для начала сделаем вывод значения и тип экземпляра этого класса в консоли:Кодclass Program {\
\
&#x20; static void Main( string\[] args ) {\
\
&#x20; DynamicClass dyn = new DynamicClass();\
&#x20; Console.WriteLine( dyn.Field + ", type " + dyn.Field.GetType() );\
&#x20; Console.ReadKey();\
\
&#x20; }\
\
}В итоге мы получили это:Код0, type System.Int32. Наш конструктор по-умолчанию сработал и полю Field был задан тип int со значением 0. Давайте делать дальше тесты. Теперь к экземпляру "dyn" присвоим значение, которое явно отличается от System.Int32, например строку и проверим результат:Кодclass Program {\
\
&#x20; static void Main( string\[] args ) {\
\
&#x20; DynamicClass dyn = new DynamicClass();\
&#x20; Console.WriteLine( dyn.Field + ", type " + dyn.Field.GetType() );\
\
&#x20; dyn.Field = "Моя тестовая строка";\
&#x20; Console.WriteLine( dyn.Field + ", type " + dyn.Field.GetType() );\
\
&#x20; Console.ReadKey();\
\
&#x20; }\
\
}Консоль нам вывела следующее:Код0, type System.Int32\
Моя тестовая строка, type System.StringО, чудо! Это настоящая метаморфоза! Давайте зададим полю Field другой экземпляр класса DynamicClass и посмотрим что из этого получится:Кодclass Program {\
\
&#x20; static void Main( string\[] args ) {\
\
&#x20; DynamicClass dyn = new DynamicClass();\
&#x20; DynamicClass dyn2 = new DynamicClass();\
\
&#x20; Console.WriteLine( dyn.Field + ", type " + dyn.Field.GetType() );\
\
&#x20; dyn.Field = "Моя тестовая строка";\
&#x20; Console.WriteLine( dyn.Field + ", type " + dyn.Field.GetType() );\
\
&#x20; dyn.Field = dyn2; // присваиваем объект класса DynamicClass\
&#x20; Console.WriteLine( dyn.Field + ", type " + dyn.Field.GetType() );\
\
&#x20; Console.ReadKey();\
\
&#x20; }\
\
}В итоге у нас консолька выведет:Код0, type System.Int32\
Моя тестовая строка, type System.String\
test.DynamicClass, type test.DynamicClassНа первый взгляд можно не понять каким образом так получилось, но объяснение лёгкое: поскольку нет конкретного(значимого) значения, C# выводит в его качестве имя типа, как от функции "GetType()". Ваши тесты могут показать немного другие значение, но не пугайтесь. Такое имя зависит от namespace, в котором был создан класс. Если Вы название проект не "test", то имя вашего DynamicClass будет иметь вид: **ВАШ\_НЕЙМСПЕЙС.DynamicClass**.\
Как и в других хороших возможностях, существует такое "Но". Здесь без исключения. Но, с таким подходом нужно быть очень аккуратным, и это в первую очередь связано с использованием методов, полей и свойств динамического типа. Если Вы набирали текст руками, то заметили, что при вводе "dyn.Field." далее не было подсказок какие методы есть в следующей цепочке. Это не баг, а так устроен "подсветчик кода". Связано это с тем, что компилятор не знает каким типом может быть поле в процессе выполнения программы. По-этому нужно тщательно проверять программу на ввод корректных данных и уже потом вызывать метод. Метод, конечно, нужно писать по-памяти.\
\
Следующим шагом будет разбор анонимных типов. Что-же это такое? Анонимные типы позволяют делать экземпляры одноразовых классов на ходу, в процессе написания кода. Естественно мы можем только догадываться какой тип нам сгенерирует компилятор, по-этому нам нужно где-то хранить результат. Для этого существует ключевое слово **var**. Это своего рода универсальный тип, который в зависимости от переданного ему значения образует его тип. Для проверки результатов, очистим метод Main и напишем несколько примеров с выводом типа и значения:Кодclass Program {\
\
&#x20; static void Main( string\[] args ) {\
\
&#x20; var anonym1 = 0;\
&#x20; var anonym2 = "анонимный тип";\
\
&#x20; Console.WriteLine( anonym1 + ", type " + anonym1.GetType() );\
&#x20; Console.WriteLine( anonym2 + ", type " + anonym2.GetType() );\
\
&#x20; Console.ReadKey();\
\
&#x20; }\
\
}Наша консоль покажет такой результат:Код0, type System.Int32\
анонимный тип, type System.StringВ таком виде ключевое слово var следует воспринимать как универсальный тип и о никакой анонимности не может быть и речи. Это слово очень помогает в скорости набора программы, поскольку в место написания какого-то километрового названия мы ограничиваемся тремя буквами(видимо, от слова Variable).\
Поскольку мы рассматривает тему анонимности, то думаю, пришло время рассмотреть способ их создания. Самый простой вариант такой:Кодvar realAnonym = new {\
&#x20; Name = "Василий",\
&#x20; Age = 23,\
&#x20; LoveColor = ConsoleColor.White\
};Практически создаётся так же, как и обычный класс или структура, но без указания типа. Теперь наша переменная "realAnonym" будет иметь в своём арсенале три свойства, которые мы указали в коде: **Name**, **Age**, **LoveColor**. Давайте проверим в нашей консоли какие типы были заданы нашим свойствам и какой тип образовался для нашего анонима:Кодstatic void Main( string\[] args ) {\
\
&#x20; var realAnonym = new {\
&#x20; Name = "Василий",\
&#x20; Age = 23,\
&#x20; LoveColor = ConsoleColor.White\
&#x20; };\
\
&#x20; Console.WriteLine( realAnonym.Name + ", type " + realAnonym.Name.GetType() );\
&#x20; Console.WriteLine( realAnonym.Age + ", type " + realAnonym.Age.GetType() );\
&#x20; Console.WriteLine( realAnonym.LoveColor + ", type " + realAnonym.LoveColor.GetType() );\
&#x20; Console.WriteLine( realAnonym + ", type " + realAnonym.GetType() );\
\
&#x20; Console.ReadKey();\
\
&#x20; }\
\
}У меня консоль получила следующие данные:КодВасилий, type System.String\
23, type System.Int32\
White, type System.ConsoleColor\
{ Name = Василий, Age = 23, LoveColor = White }, type <>f\_AnonymousType0`3&#91;System.String,System.Int32,System.ConsoleColor]<!--/uzc--></div></div><!--/uzcode-->Как видим, свойтва экземпляра были того типа, что и значение, а вот с типом этого экземпляра что-то не так <img src="http://s49.ucoz.net/sm/15/smile.gif" border="0" align="absmiddle" alt="smile" /> Если бы мы обявили так:<!--uzcode--><div class="bbCodeBlock"><div class="bbCodeName" style="padding-left:5px;font-weight:bold;font-size:7pt">Код</div><div class="codeMessage" style="border:1px inset;max-height:200px;overflow:auto;height:expression(this.scrollHeight<5?this.style.height:scrollHeight>200?'200px':''+(this.scrollHeight+5)+'px');"><!--uzc-->&lt;>f_AnonymousType0`3\[System.String,System.Int32,System.ConsoleColor] realAnonym = new {\
&#x20; Name = "Василий",\
&#x20; Age = 23,\
&#x20; LoveColor = ConsoleColor.White\
};То естественно нам компилятор упрекнул бы в плохом оформлении кода ![smile](http://s49.ucoz.net/sm/15/smile.gif) В этом нам и помог var, который в примере уже выступает как анонимный тип и позволяет работать с тем экземпляром.\
Слово var используется только в локальном контексте. Другими словами мы не можем сделать его типом свойства или поля класса, а используется он исключительно внутри методов, свойств и конструкторов/деструкторов. Но это не значит, что мы не можем использовать анонимные типы в не функций. Для самостоятельной работы попробуйте создать анонимный тип в dynamic поле и увидите ![wink](http://s49.ucoz.net/sm/15/wink.gif)\
\
Расскажу ещё несколько слов о анонимных типах, а точнее где они часто используются. В нашем примере нет необходимости в таких типах, но при разработке серьёзных программ они часто используются. В следующих уроках я дам Вам более детальный пример, а на этом, пожалуй, всё. С вами был и есть - wmysterio. Бай.|1264|1|0||anonimnye\_i\_dinamicheskie\_tipy\_v\_c|1425501811


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lessons.sannybuilder.com/00300/00100/000169.-anonimnye-i-dinamicheskie-tipy-v-c.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
