Герберт Шилдт - C# 4.0: полное руководство
- Название:C# 4.0: полное руководство
- Автор:
- Жанр:
- Издательство:ООО И.Д. Вильямс
- Год:2011
- Город:Москва -- Киев
- ISBN:978-5-8459-1684-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Герберт Шилдт - C# 4.0: полное руководство краткое содержание
В этом полном руководстве по C# 4.0 - языку программирования, разработанному специально для среды .NET, - детально рассмотрены все основные средства языка: типы данных, операторы, управляющие операторы, классы, интерфейсы, методы, делегаты, индексаторы, события, указатели, обобщения, коллекции, основные библиотеки классов, средства многопоточного программирования и директивы препроцессора. Подробно описаны новые возможности C#, в том числе PLINQ, библиотека TPL, динамический тип данных, а также именованные и необязательные аргументы. Это справочное пособие снабжено массой полезных советов авторитетного автора и сотнями примеров программ с комментариями, благодаря которым они становятся понятными любому читателю независимо от уровня его подготовки.
Книга рассчитана на широкий круг читателей, интересующихся программированием на C#.Введите сюда краткую аннотацию
C# 4.0: полное руководство - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
В объявлении класса Gen
можно указывать любое имя параметра типа, но по традиции выбирается имя Т. К числу других наиболее употребительных имен параметров типа относятся V и Е. Вы, конечно, вольны использовать и более описательные имена, например TValue
или ТКеу
. Но в этом случае первой в имени параметра типа принято указывать прописную букву Т.
Далее имя Т используется для объявления переменной ob, как показано в следующей строке кода.
Т ob; // объявить переменную типа Т
Как пояснялось выше, имя параметра типа Т служит меткой-заполнителем конкретного типа, указываемого при создании объекта класса Gen
. Поэтому переменная ob будет иметь тип, привязываемый к Т при получении экземпляра объекта класса Gen. Так, если вместо Т указывается тип string, то в экземпляре данного объекта переменная ob будет иметь тип string.
А теперь рассмотрим конструктор класса Gen
.
public Gen(T о) {
ob = о;
}
Как видите, параметр о
этого конструктора относится к типу Т. Это означает, что конкретный тип параметра о определяется типом, привязываемым к Т при создании объекта класса Gen. А поскольку параметр о и переменная экземпляра ob относятся к типу Т, то после создания объекта класса Gen
их конкретный тип окажется одним и тем же.
С помощью параметра типа Т можно также указывать тип, возвращаемый методом, как показано ниже на примере метода GetOb()
.
public Т GetOb() {
return ob;
}
Переменная ob также относится к типу Т, поэтому ее тип совпадает с типом, возвращаемым методом GetOb()
.
Метод ShowType()
отображает тип параметра Т, передавая его оператору typeof
. Но поскольку реальный тип подставляется вместо Т при создании объекта класса Gen
, то оператор typeof
получит необходимую информацию о конкретном типе.
В классе GenericsDemo
демонстрируется применение обобщенного класса Gen
. Сначала в нем создается вариант класса Gen
для типа int
.
Gen iOb;
Внимательно проанализируем это объявление. Прежде всего обратите внимание на то, что тип int
указывается в угловых скобках после имени класса Gen
. В этом случае int
служит аргументом типа, привязанным к параметру типа Т в классе Gen. В данном объявлении создается вариант класса Gen
, в котором тип Т заменяется типом int везде, где он встречается. Следовательно, после этого объявления int
становится типом переменной ob и возвращаемым типом метода GetOb()
.
В следующей строке кода переменной iOb присваивается ссылка на экземпляр объекта класса Gen
для варианта типа int
.
iOb = new Gen (102);
Обратите внимание на то, что при вызове конструктора класса Gen
указывается также аргумент типа int
. Это необходимо потому, что переменная (в данном случае — iOb), которой присваивается ссылка, относится к типу Gen
. Поэтому ссылка, возвращаемая оператором new
, также должна относиться к типу Gen
. В противном случае во время компиляции возникнет ошибка. Например, приведенное ниже присваивание станет причиной ошибки во время компиляции.
iOb = new Gen(118.12); // Ошибка!
Переменная iOb относится к типу Gen и поэтому не может использоваться для ссылки на объект типа Gen. Такой контроль типов относится к одним из главных преимуществ обобщений, поскольку он обеспечивает типовую безопасность.
Затем в программе отображается тип переменной ob в объекте iOb — тип System.Int32
. Это структура .NET, соответствующая типу int. Далее значение переменной ob получается в следующей строке кода.
int v = iOb.GetOb();
Возвращаемым для метода GetOb()
является тип Т, который был заменен на тип int при объявлении переменной iOb, и поэтому метод GetOb()
возвращает значение того же типа int
. Следовательно, данное значение может быть присвоено переменной v типа int
.
Далее в классе GenericsDemo
объявляется объект типа Gen
.
Gen strOb = new Gen("Обобщения повышают эффективность.");
В этом объявлении указывается аргумент типа string
, поэтому в объекте класса Gen вместо Т подставляется тип string
. В итоге создается вариант класса Gen
для типа string
, как демонстрируют остальные строки кода рассматриваемой здесь программы.
Прежде чем продолжить изложение, следует дать определение некоторым терминам. Когда для класса Gen
указывается аргумент типа, например int
или string
, то создается так называемый в C# закрыто сконструированный тип. В частности, Gen
является закрыто сконструированным типом. Ведь, по существу, такой обобщенный тип, как Gen
, является абстракцией. И только после того, как будет сконструирован конкретный вариант, например Gen
, создается конкретный тип. А конструкция, подобная Gen
, называется в C# открыто сконструированным типом , поскольку в ней указывается параметр типа Т, но не такой конкретный тип, как int
.
В C# чаще определяются такие понятия, как открытый и закрытый типы. Открытым типом считается такой параметр типа или любой обобщенный тип, для которого аргумент типа является параметром типа или же включает его в себя. А любой тип, не относящийся к открытому, считается закрытым. Сконструированным типом считается такой обобщенный тип, для которого предоставлены все аргументы типов. Если все эти аргументы относятся к закрытым типам, то такой тип считается закрыто сконструированным. А если один или несколько аргументов типа относятся к открытым типам, то такой тип считается открыто сконструированным.
Что касается обобщенных типов, то следует иметь в виду, что ссылка на один конкретный вариант обобщенного типа не совпадает по типу с другим вариантом того же самого обобщенного типа. Так, если ввести в приведенную выше программу следующую строку кода, то она не будет скомпилирована.
iOb = strOb; // Неверно!
Несмотря на то что обе переменные, iOb
и strOb
, относятся к типу Gen
, они ссылаются на разные типы, поскольку у них разные аргументы.
В связи с изложенным выше возникает следующий резонный вопрос: если аналогичные функциональные возможности обобщенного класса Gen
можно получить и без обобщений, просто указав объект как тип данных и выполнив надлежащее приведение типов, то какая польза от того, что класс Gen
делается обобщенным? Ответ на этот вопрос заключается в том, что обобщения автоматически обеспечивают типовую безопасность всех операций, затрагивающих класс Gen
. В ходе выполнения этих операций обобщения исключают необходимость обращаться к приведению типов и проверять соответствие типов в коде вручную.
Интервал:
Закладка: