- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
C# 4.0 полное руководство - 2011 - Герберт Шилдт
Шрифт:
Интервал:
Закладка:
В приведенном ниже примере программы применение типа dynamic демонстрируется на практике.
// Продемонстрировать применение типа dynamic, using System;
using System.Globalization;
class DynDemo {
static void Main() {
// Объявить две динамические переменные, dynamic str; dynamic val;
// Поддерживается неявное преобразование в динамические типы.
// Поэтому следующие присваивания вполне допустимы, str = "Это строка"; val = 10;
Console.WriteLine("Переменная str содержит: " + str);
Console.WriteLine("Переменная val содержит: " + val + 'n');
str = str.ToUpper (Culturelnfo.CurrentCulture);
Console.WriteLine("Переменная str теперь содержит: " + str);
val = val + 2;
Console.WriteLine("Переменная val теперь содержит: " + val + 'n');
string str2 = str.ToLower(Culturelnfo.CurrentCulture);
Console.WriteLine("Переменная str2 содержит: " + str2);
// Поддерживаются неявные преобразования из динамических типов.
int х = val * 2;
Console.WriteLine("Переменная x содержит: " + x);
}
}
Выполнение этой программы дает следующий результат.
Переменная str содержит: Это строка Переменная val содержит: 10
Переменная str теперь содержит: ЭТО СТРОКА Переменная val теперь содержит: 12
Переменная str2 содержит: это строка Переменная х содержит: 24
Обратите внимание в этой программе на две переменные str и val, объявляемые с помощью типа dynamic. Это означает, что проверка на соответствие типов операций с участием обеих переменных не будет произведена во время компиляции. В итоге для них оказывается пригодной любая операция. В данном случае для переменной str вызываются методы ToUpper () и ToLower () класса String, а переменная участвует в операциях сложения и умножения. И хотя все перечисленные выше действия совместимы с типами объектов, присваиваемых обеим переменным в рассматриваемом здесь примере, компилятору об этом ничего не известно — он просто принимает. И это, конечно, упрощает программирование динамических процедур, хотя и допускает возможность Появления ошибок в подобных действиях во время выполнения.
В разбираемом здесь примере программа ведет себя "правильно" во время выполнения, поскольку объекты, присваиваемые упомянутым выше переменным, поддерживают действия, выполняемые в программе. В частности, переменной val присваивается целое значение, и поэтому она поддерживает такие целочисленные операции, как сложение. А переменной str присваивается символьная строка, и поэтому она поддерживает строковые операции. Следует, однако, иметь в виду, что ответственность за фактическую поддержку типом объекта, на который делается ссылка, всех операций над данными типа dynamic возлагается на самого программирующего. В противном случае выполнение программы завершится аварийным сбоем.
В приведенном выше примере обращает на себя внимание еще одно обстоятельство: переменной типа dynamic может быть присвоен любой тип ссылки на объект благодаря неявному преобразованию любого типа в тип dynamic. Кроме того, тип dynamic автоматически преобразуется в любой другой тип. Разумеется, если во время выполнения такое преобразование окажется неправильным, то произойдет ошибка
при выполнении. Так, если добавить в конце рассматриваемой здесь программы следующую строку кода:
bool b = val;
то возникнет ошибка при выполнении из-за отсутствия неявного преобразования типа int (который оказывается типом переменной val во время выполнения) в тип bool. Поэтому данная строка кода приведет к ошибке при выполнении, хотя она и будет скомпилирована безошибочно.
Прежде чем оставить данный пример программы, попробуйте поэкспериментировать с ней. В частности, измените тип переменных str и val на object, а затем попытайтесь скомпилировать программу еще раз. В итоге появятся ошибки при компиляции, поскольку тип object не поддерживает действия, выполняемые над обеими переменными, что и будет обнаружено во время компиляции. В этом, собственно, и заключается основное отличие типов object и dynamic. Несмотря на то что оба типа могут использоваться для ссылки на объект любого другого типа, над переменной типа object можно производить только те действия, которые поддерживаются типом object. Если же вы используете тип dynamic, то можете указать какое угодно действие, при условии что это действие поддерживается конкретным объектом, на который делается ссылка во время выполнения.
Для того чтобы стало понятно, насколько тип dynamic способен упростить решение некоторых задач, рассмотрим простой пример его применения вместе с рефлексией. Как пояснялось в главе 17, чтобы вызвать метод для объекта класса, получаемого во время выполнения с помощью рефлексии, можно, в частности, обратиться к методу Invoke (). И хотя такой способ оказывается вполне работоспособным, нужный метод намного удобнее вызвать по имени в тех случаях, когда его имя известно. Например, вполне возможна такая ситуация, когда в некоторой сборке содержится конкретный класс, поддерживающий методы, имена и действия которых заранее известны. Но поскольку эта сборка подвержена изменениям, то приходится постоянно убеждаться в том, что используется последняя ее версия. Для проверки текущей версии сборки можно, например, воспользоваться рефлексией, сконструировать объект искомого класса, а затем вызвать методы, определенные в этом классе. Теперь эти методы можно вызвать по имени с помощью типа dynamic, а не метода Invoke (), поскольку их имена известны.
Разместите сначала приведенный ниже код в файле с именем MyClass . cs. Этот код будет динамически загружаться посредством рефлексии.
public class DivBy {
public bool IsDivBy(int a, int b) { if ( (a % b) == 0) return true; return false;
}
public bool IsEven(int a) { if ( (a % 2) == 0) return true; return false;
}
}
Затем скомпилируйте этот файл в библиотеку DLL под именем MyClass .dll. Если вы пользуетесь компилятором командной строки, введите в командной строке следующее.
Далее составьте программу, в которой применяется библиотека MyClass . dll, как показано ниже.
// Использовать тип dynamic вместе с рефлексией.
using System;
using System.Reflection;
class DynRefDemo { static void Main() {
Assembly asm = Assembly.LoadFrom("MyClass.dll");
Type[] all = asm.GetTypes();
// Найти класс DivBy. int i;
for(i =0; i < all.Length; i++) if(all[i].Name == "DivBy") break;
if(i == all.Length) {
Console.WriteLine("Класс DivBy не найден в сборке."); return;
}
Type t = all[i];
//А теперь найти используемый по умолчанию конструктор.
Constructorlnfo[] ci = t.GetConstructors();
int j ;
for(j =0; j < ci.Length; j++)
if(ci[j].GetParameters().Length == 0) break;
if(j == ci.Length) {
Console.WriteLine("Используемый по умолчанию конструктор не найден."); return;
}
I
// Создать объект класса DivBy динамически, dynamic obj = ci[j].Invoke(null);
// Далее вызвать по имени методы для переменной obj. Это вполне допустимо,
// поскольку переменная obj относится к типу dynamic, а вызовы методов // проверяются на соответствие типов во время выполнения, а не компиляции, if(obj.IsDivBy(15, 3))
Console.WriteLine("15 делится нацело на 3."); else
Console.WriteLine("15 HE делится нацело на 3.");
if(obj.IsEven(9))
Console.WriteLine("9 четное число."); else
Как видите, в данной программе сначала динамически загружается библиотека MyClass . dll, а затем используется рефлексия для построения объекта класса DivBy. Построенный объект присваивается далее переменной obj типа dynamic. А раз так, то методы Is DivBy () и IsEven () могут быть вызваны для переменной obj по имени, а не с помощью метода Invoke (). В данном примере это вполне допустимо, поскольку переменная obj на самом деле ссылается на объект класса DivBy. В противном случае выполнение программы завершилось бы неудачно.
Приведенный выше пример сильно упрощен и несколько надуман. Тем не менее он наглядно показывает главное преимущество, которое дает тип dynamic в тех случаях, когда типы получаются во время выполнения. Когда характеристики искомого типа, в том числе методы, операторы, поля и свойства, заранее известны, эти характеристики могут быть получены по имени с помощью типа dynamic, как следует из приведенного выше примера. Благодаря этому код становится проще, короче и понятнее.
Применяя тип dynamic, следует также иметь в виду, что при компиляции программы тип dynamic фактически заменяется объектом, а для описания его применения во время выполнения предоставляется соответствующая информация. И поскольку тип dynamic компилируется в тип object для целей перегрузки, то оба типа dynamic и object расцениваются как одно и то же. Поэтому при компиляции двух следующих перегружаемых методов возникнет ошибка.

