Следует особо подчеркнуть, для успешной компиляции программы в объявлении обоих типов делегатов SomeOp and AnotherOp должны быть непременно указаны ключевые слова in и out соответственно. Без этих модификаторов компиляция программы будет выполнена с ошибками из-за отсутствия неявных преобразований типов в означенных строках кода.
Создание экземпляров объектов обобщенных типов
Когда приходится иметь дело с обобщениями, то нередко возникает вопрос: не приведет ли применение обобщенного класса к неоправданному раздуванию кода? Ответ на этот вопрос прост: не приведет. Дело в том, что в C# обобщения реализованы весьма эффективным образом: новые объекты конструируемого типа создаются лишь по мере надобности. Этот процесс описывается ниже.
Когда обобщенный класс компилируется в псевдокод MSIL, он сохраняет все свои параметры типа в их обобщенной форме. А когда конкретный экземпляр класса потребуется во время выполнения программы, то JIT-компилятор сконструирует конкретный вариант этого класса в исполняемом коде, в котором параметры типа заменяются аргументами типа. В каждом экземпляре с теми же самыми аргументами типа будет использоваться один и тот же вариант данного класса в исполняемом коде.
Так, если имеется некоторый обобщенный класс Gen<T>, то во всех объектах типа Gen<T> будет использоваться один и тот же исполняемый код данного класса. Следовательно, раздувание кода исключается благодаря тому, что в программе создаются только те варианты класса, которые действительно требуются. Когда же возникает потребность сконструировать объект другого типа, то компилируется новый вариант класса в исполняемом коде.
Как правило, новый исполняемый вариант обобщенного класса создается для каждого объекта конструируемого типа, в котором аргумент имеет тип значения, например int или double. Следовательно, в каждом объекте типа Gen<int> будет использоваться один исполняемый вариант класса Gen, а в каждом объекте типа Gen<double> — другой вариант класса Gen, причем каждый вариант приспосабливается к конкретному типу значения. Но во всех случаях, когда аргумент оказывается ссылочного типа, используется
Некоторые ограничения, присущие обобщениям
Ниже перечислен ряд ограничений, которые следует иметь в виду при использовании обобщений.
• Свойства, операторы, индексаторы и события не могут быть обобщенными. Но эти элементы могут использоваться в обобщенном классе, причем с параметрами обобщенного типа этого класса.
• К обобщенному методу нельзя применять модификатор extern.
• Типы указателей нельзя использовать в аргументах типа.
• Если обобщенный класс содержит поле типа static, то в объекте
Заключительные соображения относительно обобщений
Обобщения являются весьма эффективным дополнением С#, поскольку они упрощают создание типизированного, повторно используемого кода. Несмотря на несколько усложненный, на первый взгляд, синтаксис обобщений, их применение быстро входит в привычку. Айалогично, умение применять ограничения к месту требует некоторой практики и со временем не вызывает особых затруднений. Обобщения теперь стали неотъемлемой частью программирования на С#. Поэтому освоение этого важного языкового средства стоит затраченных усилий.
ГЛАВА 19
LINQ
Без сомнения, LINQ относится к одним из самых интересных средств языка С#. Эти средства были внедрены в версии C# 3.0 и явились едва ли не самым главным его дополнением, которое состояло не только во внесении совершенно нового элемента в синтаксис С#, добавлении нескольких ключевых слов и предоставлении больших возможностей, но и в значительном расширении рамок данного языка программирования и круга задач, которые он позволяет решать. Проще говоря, внедрение LINQ стало поворотным моментом в истории развития С#.
Аббревиатура LINQ означает Language-Integrated Query, т.е.
LINQ дополняет C# средствами, позволяющими формировать запросы для любого LINQ-
