000169. Анонимные и динамические типы в c#
Last updated
Last updated
Анонимные и динамические типы в c#||wmysterio|wmysterio|wmysterio@yandex.ru|/||Всем невероятный привет! С Вами, как всегда, wmysterio, и сегодня я расскажу очередную интересную информацию о C#. Из заголовка статьи, некоторые уже догадались о чём будет идти речь, но я решил поделится со всеми желающими этими возможностями. Начну этот рассказ с динамических типов, вернее сказать типом. Его суть в том, что переменная в классе или структуре может иметь "плавающий" тип. Другими словами менять свой тип в ходе выполнения программы. Для знакомства с темами урока, давайте создадим новый проект консольного приложения. Для экспериментов создадим класс "DynamicClass" с пустым конструктором:
Кодusing System;
namespace test {
class Program {
static void Main( string[] args ) {
}
}
// Наш новый класс
public class DynamicClass {
public DynamicClass() { }
}
}Теперь нужно добавить новое слово в наш шарп-лексику - dynamic. Давайте добавим в Наш класс поле с именем "Field", и укажем в конструкторе, что оно по-умолчанию равно нулю:Код// Наш новый класс
public class DynamicClass {
public dynamic Field; // Наше динамическое поле
public DynamicClass() { Field = 0; }
}Теперь делаем тесты в функции Main. Для начала сделаем вывод значения и тип экземпляра этого класса в консоли:Кодclass Program {
static void Main( string[] args ) {
DynamicClass dyn = new DynamicClass();
Console.WriteLine( dyn.Field + ", type " + dyn.Field.GetType() );
Console.ReadKey();
}
}В итоге мы получили это:Код0, type System.Int32. Наш конструктор по-умолчанию сработал и полю Field был задан тип int со значением 0. Давайте делать дальше тесты. Теперь к экземпляру "dyn" присвоим значение, которое явно отличается от System.Int32, например строку и проверим результат:Кодclass Program {
static void Main( string[] args ) {
DynamicClass dyn = new DynamicClass();
Console.WriteLine( dyn.Field + ", type " + dyn.Field.GetType() );
dyn.Field = "Моя тестовая строка";
Console.WriteLine( dyn.Field + ", type " + dyn.Field.GetType() );
Console.ReadKey();
}
}Консоль нам вывела следующее:Код0, type System.Int32
Моя тестовая строка, type System.StringО, чудо! Это настоящая метаморфоза! Давайте зададим полю Field другой экземпляр класса DynamicClass и посмотрим что из этого получится:Кодclass Program {
static void Main( string[] args ) {
DynamicClass dyn = new DynamicClass();
DynamicClass dyn2 = new DynamicClass();
Console.WriteLine( dyn.Field + ", type " + dyn.Field.GetType() );
dyn.Field = "Моя тестовая строка";
Console.WriteLine( dyn.Field + ", type " + dyn.Field.GetType() );
dyn.Field = dyn2; // присваиваем объект класса DynamicClass
Console.WriteLine( dyn.Field + ", type " + dyn.Field.GetType() );
Console.ReadKey();
}
}В итоге у нас консолька выведет:Код0, type System.Int32
Моя тестовая строка, type System.String
test.DynamicClass, type test.DynamicClassНа первый взгляд можно не понять каким образом так получилось, но объяснение лёгкое: поскольку нет конкретного(значимого) значения, C# выводит в его качестве имя типа, как от функции "GetType()". Ваши тесты могут показать немного другие значение, но не пугайтесь. Такое имя зависит от namespace, в котором был создан класс. Если Вы название проект не "test", то имя вашего DynamicClass будет иметь вид: ВАШ_НЕЙМСПЕЙС.DynamicClass.
Как и в других хороших возможностях, существует такое "Но". Здесь без исключения. Но, с таким подходом нужно быть очень аккуратным, и это в первую очередь связано с использованием методов, полей и свойств динамического типа. Если Вы набирали текст руками, то заметили, что при вводе "dyn.Field." далее не было подсказок какие методы есть в следующей цепочке. Это не баг, а так устроен "подсветчик кода". Связано это с тем, что компилятор не знает каким типом может быть поле в процессе выполнения программы. По-этому нужно тщательно проверять программу на ввод корректных данных и уже потом вызывать метод. Метод, конечно, нужно писать по-памяти.
Следующим шагом будет разбор анонимных типов. Что-же это такое? Анонимные типы позволяют делать экземпляры одноразовых классов на ходу, в процессе написания кода. Естественно мы можем только догадываться какой тип нам сгенерирует компилятор, по-этому нам нужно где-то хранить результат. Для этого существует ключевое слово var. Это своего рода универсальный тип, который в зависимости от переданного ему значения образует его тип. Для проверки результатов, очистим метод Main и напишем несколько примеров с выводом типа и значения:Кодclass Program {
static void Main( string[] args ) {
var anonym1 = 0;
var anonym2 = "анонимный тип";
Console.WriteLine( anonym1 + ", type " + anonym1.GetType() );
Console.WriteLine( anonym2 + ", type " + anonym2.GetType() );
Console.ReadKey();
}
}Наша консоль покажет такой результат:Код0, type System.Int32
анонимный тип, type System.StringВ таком виде ключевое слово var следует воспринимать как универсальный тип и о никакой анонимности не может быть и речи. Это слово очень помогает в скорости набора программы, поскольку в место написания какого-то километрового названия мы ограничиваемся тремя буквами(видимо, от слова Variable).
Поскольку мы рассматривает тему анонимности, то думаю, пришло время рассмотреть способ их создания. Самый простой вариант такой:Кодvar realAnonym = new {
Name = "Василий",
Age = 23,
LoveColor = ConsoleColor.White
};Практически создаётся так же, как и обычный класс или структура, но без указания типа. Теперь наша переменная "realAnonym" будет иметь в своём арсенале три свойства, которые мы указали в коде: Name, Age, LoveColor. Давайте проверим в нашей консоли какие типы были заданы нашим свойствам и какой тип образовался для нашего анонима:Кодstatic void Main( string[] args ) {
var realAnonym = new {
Name = "Василий",
Age = 23,
LoveColor = ConsoleColor.White
};
Console.WriteLine( realAnonym.Name + ", type " + realAnonym.Name.GetType() );
Console.WriteLine( realAnonym.Age + ", type " + realAnonym.Age.GetType() );
Console.WriteLine( realAnonym.LoveColor + ", type " + realAnonym.LoveColor.GetType() );
Console.WriteLine( realAnonym + ", type " + realAnonym.GetType() );
Console.ReadKey();
}
}У меня консоль получила следующие данные:КодВасилий, type System.String
23, type System.Int32
White, type System.ConsoleColor
{ Name = Василий, Age = 23, LoveColor = White }, type <>f_AnonymousType03[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--><>f_AnonymousType0
3[System.String,System.Int32,System.ConsoleColor] realAnonym = new {
Name = "Василий",
Age = 23,
LoveColor = ConsoleColor.White
};То естественно нам компилятор упрекнул бы в плохом оформлении кода В этом нам и помог var, который в примере уже выступает как анонимный тип и позволяет работать с тем экземпляром.
Слово var используется только в локальном контексте. Другими словами мы не можем сделать его типом свойства или поля класса, а используется он исключительно внутри методов, свойств и конструкторов/деструкторов. Но это не значит, что мы не можем использовать анонимные типы в не функций. Для самостоятельной работы попробуйте создать анонимный тип в dynamic поле и увидите
Расскажу ещё несколько слов о анонимных типах, а точнее где они часто используются. В нашем примере нет необходимости в таких типах, но при разработке серьёзных программ они часто используются. В следующих уроках я дам Вам более детальный пример, а на этом, пожалуй, всё. С вами был и есть - wmysterio. Бай.|1264|1|0||anonimnye_i_dinamicheskie_tipy_v_c|1425501811