- •Конспект лекций по курсу «Сети эвм» Часть 2 Сурков д.А.
- •Сравнительная характеристика технологий .Net и Java
- •Общее для Java и .Net.
- •Управление памятью в .Net
- •Процедурные типы данных (делегаты)
- •Динамические массивы
- •Многозадачность
- •1: Добавление в очередь ThreadPool нового делегата, который будет запускаться в отдельном потоке (из пула свободного потока). Делегат отработал – поток обратно в пул.
- •Исключительные ситуации
- •Шаблоны в с# (появились недавно в .Net 2.0)
- •В с# в шаблонах введено понятие итератора.
- •Массивы
- •Метод Get в SystemArray
- •Средства удалённого вызова .Net Remoting
- •Пользовательские атрибуты
- •Inherited – будем ли создавать атрибут для наследника.
- •Защищённые информационные системы. Технология “Эльбрус”
- •Защищенная файловая система
Шаблоны в с# (появились недавно в .Net 2.0)
Шаблоны – это способ обобщенного программирования.
Пример:
public class Stack<T> // в < > указываются параметры, Т – тип параметров
{ // Stack – обобщенный класс
private T [ ] items; // объявляем массив
int current;
public void Push( T data)
{
current ++ ;
items[current] = data;
}
public T Pop( )
{
T result = items[current];
current --;
return result;
}
}
Класс Stack предназначен для работы со стеком некоторых объектов, тип которых заранее неизвестен. Шаблоны в С# отличаются от шаблонов С++ тем, что шаблоны в С++ - это большая макроподстановка. При использовании шаблона
(например,
Stack<Control> S = new Stack<Controls> (),
где Stack – это префикс, а Control – суффикс, с которым работает шаблон)
компилятор выполняет макроподстановку. В С++ компилятор подставит тип Control. Это делается на этапе компиляции программы:
-
При этом если в шаблоне есть синтаксическая ошибка, то о ее существовании узнаем только при создании объекта, использующего шаблон.
-
У шаблона некоторые компиляторы компилируют не весь шаблон сразу, а только использованные методы (это в С++), т.е. будет проверена корректность синтаксиса конструктора. Для проверки синтаксиса метода необходимо его вызвать:
S.Push();
-
Создание, объявление в разных .cpp модулях новых реализаций класса Stack<Control> S2 в С++ приводит к созданию двух одинаковых реализаций шаблонов. Они будут в разных объектных модулях, и линкер должен «догадаться», что это один и тот же шаблон, но он не всегда их воспринимает как одну реализацию.
-
Из шаблона в С++ сделать dll- библиотеку нельзя, т.к. конкретная реализация шаблона будет дублироваться.
-
Как правило, в программах используется много ссылочных типов данных, и если есть ссылочные объекты, то ссылка – это указатель. В С++ если пишем Stack<Control>… , а у Control-a есть наследник Button : Stack<Button> S2, то линкер не догадается, что это одно и то же. Но физически эти классы абсолютно эквивалентны, т.е. будет дублирование одной и той же реализации класса.
Button
C++: Stack <Control *> stack;
C# : Stack <Control> stack = new Stack <Control>;
Если в контейнере есть объекты ссылочных типов, то есть автоматическое преобразование типов.
При использовании шаблонов в С++ нельзя указать при объявлении шаблона, какие требования предъявляются к типу данных, которые выступают в качестве параметра.
Например, если в С++ объявлен шаблон:
template <class T> calss Stack
{
T* current;
void DoSomething
{
current -> DoSomething( );
}
}
Только на этапе компиляции программы, которая создают экземпляр шаблонного класса, параметризованный конкретным типом, происходит компиляция кода метода DoSomething, и только на этапе компиляции проверяется, что в объекте есть этот метод. Никаких средств указать: а что должен поддерживать класс T при параметризации для разработчика не предоставляется.
Если в программе где-то написать stack.DoSomething(), то будет ошибка ERROR Compilation.
В C# шаблоны доработаны. По сути это совсем другие шаблоны.
Пример:
public class Dictionary <K,V> where K: IComparable,IEnumerable
{
public V Find (K key)
{
for (int 0; i< Keys.Length; ++i)
if (key.CompareTo(Keys[i]) == 0)
return Values[i];
return null;
}
…
}
K – параметризация типом ключа
V – параметризация типом значения
where – ключевое слово, с помощью которого можно определить дополнительные ограничения (у нас K: IComparable – тип, передаваемый в шаблон, должен поддерживать интерфейс IComparable IEnumerable)
т.к. используется метод CompareTo, то мы написали поддержку интерфейса IComarable.
При создании экземпляра шаблона:
Dictionary <string, Control> dict = …
сразу идёт проверка компилятором того, поддерживает ли string интерфейс IComparable.
( CompareTo возвращает: -1, если A1<A2
0, если A1=A2
1, если A1>A2)
Основные изменения коснулись эффективности использования:
-
в С++ шаблоны нельзя было помещать в модули. В С# шаблоны компилируются, располагаются в .cs файлах, компилируется и создаётся библиотека шаблонов, она содержит код порождения классов, т.е. библиотека генерирует программный код.
При генерации происходит обращение к библиотеке с запросом на генерацию программного кода с нужными параметрами. Если такой класс уже генерировался, то он не генерируется, а даётся ссылка на уже сгенерированный.
Если захватывается экземпляр класса, у которого параметры являются ссылочными, то библиотека возвращает один и тот же экземпляр класса для всех ссылочных аргументов независимо от их типа. Физическая реализация для параметров ссылочного типа всегда одна и та же.
Для размерных типов библиотека порождения создаёт новый экземпляр класса, который реализует шаблон. Причём реализация получается эффективной, т.к. шаблонный класс содержит в себе динамический массив элементов. Тип данных шаблона – тип элемента. Для ссылочных типов – это массив ссылок, для размерных типов– это массив структур.
В Java нет разделения на ссылочные и размерные типы, и если есть динамический массив, то это всегда массив указателей. Также шаблоны в Java отличаются от шаблонов в C# ещё и тем, что в C# информация о шаблонах помещается в метаданные. С помощью метаинформации можно узнать, какие шаблоны есть в библиотеке и с какими параметрами.
В Java после компиляции в программе шаблона не остаётся.