
- •1. Понятие модуля. Принципы модульного программирования. Понятие объекта как динамического модуля.
- •2. Понятие класса. Понятие метода. Представление метода в виде обычной процедуры. Понятие конструктора и деструктора.
- •3. Понятие свойства. Методы получения и установки значений свойств. Свойства-массивы (в некоторых языках программирования). Индексаторы (в некоторых языках программирования).
- •Информация о типе времени выполнения программы
- •5. Классы в программных модулях. Атрибуты доступа к элементам объектов. Термин «инкапсуляция».
- •Термин «инкапсуляция»
- •Virtual – в базовом классе
- •7. Понятие ссылки на метод объекта (или делегата – в зависимости от языка программирования). Понятие события. Применение ссылок на методы для расширения объектов.
- •8. Понятие метакласса (в некоторых языках программирования). Методы, применяемые к классам. Виртуальные конструкторы (в некоторых языках).
- •Понятие метакласса (в некоторых языках программирования)
- •Виртуальные конструкторы (в некоторых языках)
- •3) Finally – вызвать free.
- •Если глобально-уникальный идентификатор назначается интерфейсу, то он записывается после ключевого слова interface и заключается в квадратные скобки, например:
- •Microsoft Visual Studio
- •Import Network;
- •Var Stat: SocketStat;
- •Var SocketStatCollection: … ;
- •Конструкторы и деструкторы
- •Стандартные конструкторы
- •Создание объектов по значению (на стеке) и по ссылке (в динамической памяти)
- •Операторы new и delete
- •Размещающий оператор new
- •Порядок конструирования и разрушения объектов
- •Вложенные определения классов
- •«Друзья» класса
- •Статические члены класса
- •19. Перегрузка бинарных операторов. Перегрузка унарных операторов. Перегрузка операторов преобразования типа.
- •Индексаторы
- •Механизм вызова событий
- •Создание пользовательских обобщенных коллекций
- •Создание обобщенных интерфейсов
- •Несколько слов о вложенных делегатах
- •25. Понятие итератора в языке c#. Оператор foreach. Оператор yield.
- •И напоследок... Блок finally
- •26. Понятие атрибутов в языке c#. Создание пользовательских атрибутов. Анализ атрибутов во время выполнения программы. Понятие рефлексии (reflection) в языке c#. Сериализация объектов.
- •Что такое метаданные и зачем они нужны?
- •1. Метаданные в .Net обязательны и универсальны.
- •2. Метаданные в .Net общедоступны.
- •3. Метаданные в .Net исчерпывающи.
- •4. Метаданные в .Net расширяемы.
- •5. Метаданные в .Net конструируемы программно.
- •Получение экземпляра класса Type
- •Динамическая загрузка сборок
- •Динамическая загрузка типов
- •Исследование типа
- •Характеристики типа как целого
- •Члены класса
- •Исследование объекта
- •Динамическое создание объекта и вызов методов
- •Создание объекта по его типу
- •Декларативное программирование
- •Новые механизмы абстракции?
- •Динамическое создание типов
- •Роль графов объектов
- •Formatter сериализации
- •XmlSerializer
- •Интерфейсы iFormatter и iRemotingFormatter
- •Точность типов среди форматеров
- •28*. Ооп в языке программирования Smalltalk. Достоинства и недостатки этого языка в сравнениии с языком программирования c#.
Механизм вызова событий
The List<T> class declares a single event member called Changed, which indicates that a new item has been added to the list. The Changed event is raised by the OnChanged virtual method, which first checks whether the event is null (meaning that no handlers are present). The notion of raising an event is precisely equivalent to invoking the delegate represented by the event—thus, there are no special language constructs for raising events.
Clients react to events through event handlers. Event handlers are attached using the += operator and removed using the -= operator. The following example attaches an event handler to the Changed event of a List<string>.
using System;
class Test { static int changeCount;
static void ListChanged(object sender, EventArgs e) { changeCount++; }
static void Main() { List<string> names = new List<string>(); names.Changed += new EventHandler(ListChanged); names.Add("Liz"); names.Add("Martha"); names.Add("Beth"); Console.WriteLine(changeCount); // Outputs "3" } }
For advanced scenarios where control of the underlying storage of an event is desired, an event declaration can explicitly provide add and remove accessors, which are somewhat similar to the set accessor of a property.
24. Обобщенные классы в языке C# и их отличие от шаблонов классов в языке C++. Установка ограничений на параметры обобщенных классов. Обобщенные делегаты.
Обобщенные классы в языке C# и их отличие от шаблонов классов в языке C++
Обобщенные типы присутствуют во многих библиотеках базовых классов .NET, но пространство имен System.Collections.Generic буквально наполнено ими. Подобно своему “родственнику” без обобщений (System.Collections), пространство имен System.Collections.Generic содержит множество типов класса и интерфейса, что позволяет вкладывать элементы в самые разные контейнеры.
ПРИМЕЧАНИЕ По соглашению для обобщенных типов их замещаемые параметры обозначаются буквами верхнего регистра. И хотя здесь допустимо использовать любые буквы (или слова), обычно используют T для обозначения типов, K — для ключей, а V — для значений. |
В пространстве имен System.Collections.Generic определяется и ряд классов, реализующих многие из этих ключевых интерфейсов.
Обобщенный класс |
Необобщенный аналог в System.Collections |
Описание |
Collection<T> |
CollectionBase |
База для обобщенной коллекции |
Comparer<T> |
Comparer |
Выполняет сравнение двух обобщенных объектов |
Dictionary<K, V> |
Hashtable |
Обобщенная коллекция пар имен и значений |
List<T> |
ArrayList |
Список элементов с динамически изменяемыми размерами |
Queue<T> |
Queue |
Обобщенная реализация списка FIFO (дисциплина обслуживания типа “очередь”) |
SortedDictionary<K, V> |
SortedList |
Обобщенная реализация сортированного набора пар имен и значений |
Stack<T> |
Stack |
Обобщенная реализация списка LIFO (дисциплина обслуживания типа “стек”) |
LinkedList<T> |
— |
Обобщенная реализация двусвязного списка |
ReadOnlyCollection<T> |
ReadOnlyCollectionBase |
Обобщенная реализация набора элементов только для чтения |
Тип List<T>
Подобно необобщенным классам, обобщенные классы являются объектами, размещаемыми в динамической памяти, поэтому для них следует использовать new со всеми необходимыми аргументами конструктора. Кроме того, вы должны указать типы, замещающие параметры, определенные обобщенным типом. Так, для System.Collections.Generic.List<T> требуется указать одно значение, задающее вид элемента, с которым будет функционировать List<T>. Например, чтобы создать три объекта List<> для хранения целых чисел, объектов SportsCar и объектов Person, вы должны записать следующее.
static void Main(string[] args) { // Создается List для хранения целых чисел. List<int> myInts = new List<int>();
// Создается List для хранения объектов SportsCar. List<SportsCar> myCars = new List<SportsCar>();
// Создается List для хранения объектов Person. List<Person> myPeople = new List<Person>(); } |
Когда вы создаете тип List<T> и указываете для него SportsCar, это эквивалентно следующему определению типа List<T>.
namespace System.Collections.Generic { public class List<SportsCar> : IList<SportsCar>, ICollection<SportsCar>, IEnumerable<SportsCar>, IList, ICollection, IEnumerable { ... public void Add(SportsCar item); public IList<SportsCar> AsReadOnly(); public int BinarySearch(SportsCar item); public bool Contains(SportsCar item); public void CopyTo(SportsCar[] array); public int FindIndex(System.Predicate<SportsCar> match); public SportsCar FindLast(System.Predicate<SportsCar> match); public bool Remove(SportsCar item); public int RemoveAll(System.Predicate<SportsCar> match); public SportsCar [] ToArray(); public bool TrueForAll(System.Predicate<SportsCar> match); public SportsCar this[int index] { get; set; } ... } } |
// Этот метод переставляет любые два элемента, // определенные параметром типа <T>. static void Swap<T>(ref T a, ref T b) { T temp; temp = a; a = b; b = temp; } |
Swap<int>(ref a, ref b);
При вызове обобщенных методов, подобных Swap<T>, у вас есть возможность не указывать параметр типа, но только в том случае, когда обобщенный метод требует указания аргументов, поскольку тогда компилятор может “выяснить” тип этих аргументов на основе вводимых параметров.
// Компилятор будет предполагать System.Boolean. bool b1 = true, b2 = false; Console.WriteLine("До обмена: {0}, {1}", b1, b2); Swap(ref b1, ref b2); Console.WriteLine("После обмена: {0}, {1}", b1, b2); |
Но если, например, у вас есть обобщенный метод с именем DisplayBaseClass<T>, не имеющий входных параметров, как показано ниже:
static void DisplayBaseClass<T>() { Console.WriteLine("Базовым классом {0} является: {1}.", typeof(T), typeof(T).BaseType); } |
то при вызове этого метода вы должны указать параметр типа.
В данном случае обобщенные методы Swap<T> и DisplayBaseClass<T> были определены в рамках объекта приложения (т.е. в рамках типа, определяющего метод Main()). Если вы предпочтете определить эти члены в новом типе класса (MyHelperClass), то должны записать следующее.
public class MyHelperClass { public static void Swap<T>(ref T a, ref T b) { Console.WriteLine("Методу Swap() передано {0}", typeof(T)); T temp; temp = a; a = b; b = temp; }
public static void DisplayBaseClass<T>() { Console.WriteLine("Базовым классом {0} является: {1}.", typeof(T), typeof(T).BaseType); } } |
Обратите внимание на то, что тип MyHelperClass сам по себе не является обобщенным, но определяет два обобщенных метода. Так или иначе, теперь, когда методы Swap<T> и DisplayBaseClass<T> находятся в контексте нового типа класса, при вызове их членов придется указать имя типа.
MyHelperClass.Swap<int>(ref a, ref b); |
Наконец, обобщенные методы не обязаны быть статическими. Если бы Swap<T> и DisplayBaseClass<T> были методами уровня экземпляра, нужно было бы просто создать экземпляр MyHelperClass и вызвать их из объектной переменной.
MyHelperClass c = new MyHelperClass(); c.Swap<int>(ref a, ref b); |
// Обобщенная структура Point. public struct Point<T> { // Обобщенные данные. private T xPos; private T yPos;
// Обобщенный конструктор. public Point(T xVal, T yVal) { xPos = xVal; yPos = yVal; }
// Обобщенные свойства. public T X { get { return xPos; } set { xPos = value; } }
public T Y { get { return yPos; } set { yPos = value; } }
public override string ToString() { return string.Format("[{0}, {1}]", xPos, yPos); }
// Переустановка полей со значениями параметра типа, // принятыми по умолчанию. public void ResetPoint() { xPos = default(T); yPos = default(T); } } |
В C# 2005 ключевое слово default получило два значения. Кроме использования в конструкции switch, оно может использоваться для установки параметрам типа значений, принятых по умолчанию. И это, очевидно, полезно, поскольку обобщенный тип ничего заранее не знает о фактических замещающих значениях и поэтому не может с безопасностью предполагать о том, каким должно быть значение по умолчанию. Значения по умолчанию для параметра типа являются следующими.
Для числовых значений значением по умолчанию является 0.
Для ссылочных типов значением по умолчанию является null.
Поля структуры устанавливаются равными 0 (для типов, характеризуемых значениями) или null (для ссылочных типов).