- •Основы c#. Урок 1. Что такое c#?
- •Основы c#. Урок 2. Что такое net Runtime?
- •Основы c#. Урок 3. Первая программа на c#
- •Основы c#. Урок 4. Переменные языка c#
- •Основы c#. Урок 5. Логические операторы
- •Основы c#. Урок 6. Массивы в c#
- •Основы c#. Урок 7. Операторы if и switch
- •Основы c#. Урок 8. Циклы for и foreach
- •Основы c#. Урок 10. Классы в c#
- •Основы c#. Урок 9. Цикл while
- •Основы c#. Урок 11. Конструкторы классов
- •Основы c#. Урок 12. Наследование
- •Основы c#. Урок 13. Запись в экземпляр базового класса экземпляра производного
- •Основы c#. Урок 14. Вложенные классы
- •Основы c#. Урок 15. Перегрузка бинарных операторов
- •Основы c#. Урок 16. Перегрузка унарных операторов
- •Основы c#. Урок 17. Область видимости
- •Основы c#. Урок 18. Виртуальные функции
- •Основы c#. Урок 19. Абстрактные классы
- •Основы c#. Урок 20. Запрещение наследования или модификатор sealed
- •Основы c#. Урок 21. Статические переменные
- •Основы c#. Урок 22. Статические методы класса
- •Основы c#. Урок 23. Статические конструкторы
- •Основы c#. Урок 24. Закрытые конструкторы или классы без экземпляров
- •Основы c#. Урок 25. Передача параметров переменой длины
- •Основы c#. Урок 26. Строки (класс System.String)
- •Основы c#. Урок 27. Строки (класс StringBuilder)
- •Основы c#. Урок 28. Передача параметров по ссылке и по значению (ref и out)
- •Основы c#. Урок 29. Пример передачи по ссылке
- •Основы c#. Урок 30. Перегрузка
- •Основы c#. Урок 31. Функции класса System.Array
- •Основы c#. Урок 32. Делегаты
- •Основы c#. Урок 33. События
- •Основы c#. Урок 34. Пример класса с событием
- •Основы c#. Урок 35. Введение в атрибуты
- •Основы c#. Урок 36. Пример пользовательского атрибута
- •Основы c#. Урок 37. Параметры командной строки
- •Основы c#. Урок 38. Метод Main в отдельном классе
- •Основы c#. Урок 39. Форматированный вывод
- •Основы c#. Урок 40. Класс System.Object
- •Основы c#. Урок 41. Методы класса System.Object
- •Основы c#. Урок 42. Переопределяем методы класса System.Object
- •Основы c#. Урок 43. Константы
- •Основы c#. Урок 44. Модификаторы доступа
- •Основы c#. Урок 45. Ссылка на текущий экземпляр класса (this)
- •Основы c#. Урок 46. Класс Environment
- •Основы c#. Урок 47. Работаем со специальными папками
- •Основы c#. Урок 48. Получаем список всех дисков
- •Основы c#. Урок 49. Ввод/вывод в c# (System.Io)
- •Основы c#. Урок 50. Классы для работы с папками и файлами
- •Основы c#. Урок 51. Класс Directory
- •Основы c#. Урок 52. Класс File
- •Основы c#. Урок 53. Класс FileSystemInfo
- •Основы c#. Урок 54. Класс DirectoryInfo
- •Основы c#. Урок 55. Перечисление FileAttributes
- •Основы c#. Урок 56. Класс FileInfo
- •Основы c#. Урок 57. Пример: получение имен всех подпапок
- •Основы c#. Урок 58. Класс Path
- •Основы c#. Урок 59. Класс FileSystemWatcher
- •Основы c#. Урок 60. Перечисление NotifyFilters
- •Основы c#. Урок 61. Перечисление WatcherChangeTypes
- •Основы c#. Урок 62. Класс FileSystemWatcher - пример использования
- •Основы c#. Урок 63. Сериализация класса
- •Основы c#. Урок 64. Класс BitArray
- •Основы c#. Урок 65. Класс Stack
- •Основы c#. Урок 66. Класс SortedList
- •Основы c#. Урок 67. Конвертация типов через класс Convert
- •Основы c#. Урок 68. Работа с перечислениями (enum)
- •Основы c#. Урок 69. Использование атрибута Flags для перечисления
- •Основы c#. Урок 70. Использование атрибута Flags для перечисления 2
- •Основы c#. Урок 71. Nullable типы
- •Основы c#. Урок 72. Reflection - динамическое создание кода
- •Основы c#. Урок 73. Reflection - создание enum'ов
Основы c#. Урок 70. Использование атрибута Flags для перечисления 2
Одна из часто встрчающихся задач для перечисления с атрибутом Flags - это выяснение, присутствует ли некое значение перечисления в соотвествующей переменной. Например
Вот пример такого кода:
// Объявление перечисления.
[Flags()]
public enum MilitaryType
{
Marine = 1,
Land = 2,
Cosmic = 4,
MarineAndLand = Marine | Land
}
class Program
{
static void Main(string[] args)
{
MilitaryType type = MilitaryType.MarineAndLand;
// Содержится ли в переменной значение MilitaryType.Marine?
if ((type & MilitaryType.Marine) == MilitaryType.Marine)
{
Console.WriteLine("Marine");
}
else {
Console.WriteLine("Isn't marine");
}
// Содержится ли в переменной значение MilitaryType.Cosmic?
if ((type & MilitaryType.Marine) == MilitaryType.Cosmic)
{
Console.WriteLine("Cosmic");
}
else
{
Console.WriteLine("Isn't cosmic");
}
// Содержится ли в переменной значение MilitaryType.MarineAndLand?
if ((type & MilitaryType.MarineAndLand) == MilitaryType.MarineAndLand)
{
Console.WriteLine("MarineAndLand");
}
else
{
Console.WriteLine("Isn't marine or land");
}
}
}
Как вы видите, мы тут используем побитовое И. Для данного фрагмента на экране выведется два положительных ответа (для первой и последней проверки) и один отрицательный (для второй проверки).
Основы c#. Урок 71. Nullable типы
Как известно, value-типы (к ним относятся, например, int, byte и другие) не могут принимать значение null. Что, в общем-то, вполне естественно. Но иногда такая потребность возникает. Например, при работе с базами данных - в столбце таблицы могут хранится значения целого типа и, кроме того, могут допускаться неопределенные значения (NULL). В .NET 2.0 для этого появилась такая возможность - а именно так называемые nullable-типы. Они могут принимать, кроме собственно значений соотвествующего типа, значение null.
Вот пример объявления переменной такого типа и ее использования:
Nullable<int> n;
n = null;
Синтаксис тут простой - мы мы в угловых скобках указываем нужный тип (int в нашем случае).
Для объявления nullable типов, кроме указанного синтаксиса, можно использовать и упрощенный:
int? n;
С точки зрения реализации все nullable-типы являются экземплярами структуры System.Nullable.
Основы c#. Урок 72. Reflection - динамическое создание кода
Иногда нам требуется динамически создать некий код. Естественно, что этот код у нас будет храниться в некоторой сборке. При этом сама созданная динамически сборка может существовать только в памяти или же может быть сохраненной на диск в виде файла. Сейчас мы посмотрим, как это можно сделать.
Для начала небольшое замечание по порядку создания соответствующих объектов. Сначала мы должны сгенерировать сборку, затем на основании этой сборки - модуль, потом на основании этого модуля - тип (например, класс), потом на основании этого типа (класса) - его члены (конструкторы, методы и т. п.). И, уже в самом конце, мы создаем непосредственно сгенерированный на предыдущих шагах тип.
Вот пример такого кода:
// Создание имени сборки.
AssemblyName an = new AssemblyName("MyAssembly");
an.Version = new Version("1.0.0.0");
// Создание сборки.
AssemblyBuilder ab;
ab = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Save);
// Создание модуля в сборке.
ModuleBuilder mb = ab.DefineDynamicModule("MyModule", "My.dll");
// Создание типа в сборке.
TypeBuilder tb = mb.DefineType("MyClass", TypeAttributes.Public);
// Создание конструктора без параметров.
ConstructorBuilder cb0 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null);
// Добавление кода для конструктора.
ILGenerator il0 = cb0.GetILGenerator();
il0.Emit(OpCodes.Ret);
// Создание конструктора с параметром типа string.
ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public,
CallingConventions.Standard, new Type[] { typeof(string)});
// Добавление кода для конструктора.
ILGenerator il = cb.GetILGenerator();
il.EmitWriteLine("Constructor");
il.Emit(OpCodes.Ret);
// Непосредственное создание типа.
tb.CreateType();
// Сохранение типа в файл.
ab.Save("qqq.dll");
Приведенный код при запуске создаст на жестком диске файл qqq.dll, в котором будет класс с 2-я конструкторами, причем второй конструктор будет при вызове выводить строчку "Constructor".
Несколько пояснений по коду.
Первое. Очень часто при создании типов и членов этих типов надо указать их атрибуты (модификаторы доступа типа public и т. п.). Это мы делаем через перечисления TypeAttributes и MethodAttributes, которое содержит соотвествующие значения (Public, например). Несколько необходимых значений из этих перечислений можно соединить через побитовое "или".
Второе. Метод Emit класса ILGenerator в качестве параметра принимает перечисление OpCodes, которое фактически содержит инструкции на языке IL - языке, который является аналогом для .NET обычного ассемблера. Это означает, что его инструкции не столь очевидны для реального программирования - именно поэтому в качестве примера таких IL-инструкций и была приведена самая простая из них - а именно выход из функции (OpCodes.Ret).
