Полное руководство. С# 4.0
Полное руководство. С# 4.0 читать книгу онлайн
В этом полном руководстве по C# 4.0 — языку программирования, разработанному специально для среды .NET, — детально рассмотрены все основные средства языка: типы данных, операторы, управляющие операторы, классы, интерфейсы, методы, делегаты, индексаторы, события, указатели, обобщения, коллекции, основные библиотеки классов, средства многопоточного программирования и директивы препроцессора. Подробно описаны новые возможности C#, в том числе PLINQ, библиотека TPL, динамический тип данных, а также именованные и необязательные аргументы. Это справочное пособие снабжено массой полезных советов авторитетного автора и сотнями примеров программ с комментариями, благодаря которым они становятся понятными любому читателю независимо от уровня его подготовки.Книга рассчитана на широкий круг читателей, интересующихся программированием на C#.
В данной книге вы найдете:- Полное описание средств языка C#- Подробное рассмотрение новых средств в версии C# 4.0, в том числе PLINQ, библиотеку TPL, именованные и необязательные аргументы, динамический тип данных и многое другое- Сотни простых и понятных примеров программ с комментариями.- Самый полный источник информации по C#Благодаря поддержке параллельного языка интегрированных запросов (PLINQ) и библиотеки распараллеливания задач (TPL) версия 4.0 стала новой вехой в программировании на C#, и поэтому Герберт Шилдт, автор лучших книг по программированию, обновил и расширил свое классическое руководство, чтобы охватить в нем эти и другие нововведения. В книге подробно описываются языковые средства C#, даются профессиональные рекомендации и приводятся сотни примеров программ, охватывающих все аспекты программирования на C#, включая синтаксис, ключевые слова и основные библиотеки, не говоря уже о таких новшествах, как PLINQ, TPL, динамический тип данных, а также именованные и необязательные аргументы.Это необходимое каждому программирующему на C# справочное руководство написано простым и доступным языком, благодаря которому Герберт Шилдт стал таким популярным. В книге найдут ответы на насущные вопросы по C# как начинающие, так и опытные программисты.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Применительно к обобщенному интерфейсу ковариантность служит средством,разрешающим методу возвращать тип, производный от класса, указанного в параметре типа. В прошлом возвращаемый тип должен был в точности соответствоватьпараметру типа в силу строгой проверки обобщений на соответствие типов. Ковариантность смягчает это строгое правило таким образом, чтобы обеспечить типовуюбезопасность. Параметр ковариантного типа объявляется с помощью ключевого словаout, которое предваряет имя этого параметра.
Для того чтобы стали понятнее последствия применения ковариантности, обратимся к конкретному примеру. Ниже приведен очень простой интерфейс IMyCoVarGenIF,в котором применяется ковариантность.// В этом обобщенном интерфейсе поддерживается ковариантность.public interface IMyCoVarGenIF<out Т> { Т GetObject();}
Обратите особое внимание на то, как объявляется параметр обобщенного типа Т.Его имени предшествует ключевое слово out. В данном контексте ключевое слово outобозначает, что обобщенный тип Т является ковариантным. А раз он ковариантный, тометод GetObject() может возвращать ссылку на обобщенный тип Т или же ссылку налюбой класс, производный от типа Т.
Несмотря на свою ковариантность по отношению к обобщенному типу Т, интерфейс IMyCoVarGenIF реализуется аналогично любому другому обобщенному интерфейсу. Ниже приведен пример реализации этого интерфейса в классе MyClass.// Реализовать интерфейс IMyCoVarGenIF.class MyClass<T> : IMyCoVarGenIF<T> { T obj; public MyClass(T v) { obj = v; } public T GetObject() { return obj; }}
Обратите внимание на то, что ключевое слово out не указывается еще раз в выражении, объявляющем реализацию данного интерфейса в классе MyClass. Это не тольконе нужно, но и вредно, поскольку всякая попытка еще раз указать ключевое слово outбудет расцениваться компилятором как ошибка.
А теперь рассмотрим следующую простую реализацию иерархии классов.// Создать простую иерархию классов.class Alpha { string name; public Alpha(string n) { name = n; } public string GetName() { return name; } // ...}class Beta : Alpha { public Beta(string n) : base(n) { } // ...}
Как видите, класс Beta является производным от класса Alpha.С учетом всего изложенного выше, следующая последовательность операций будетсчитаться вполне допустимой.// Создать ссылку из интерфейса IMyCoVarGenIF на объект типа MyClass<Alpha>.// Это вполне допустимо как при наличии ковариантности, так и без нее.IMyCoVarGenIF<Alpha> AlphaRef = new MyClass<Alpha>(new Alpha("Alpha #1"));Console.WriteLine("Имя объекта, на который ссылается переменная AlphaRef: " +AlphaRef.GetObject().GetName());// А теперь создать объект MyClass<Beta> и присвоить его переменной AlphaRef.// *** Эта строка кода вполне допустима благодаря ковариантности. ***AlphaRef = new MyClass<Beta>(new Beta("Beta #1"));Console.WriteLine("Имя объекта, на который теперь ссылается " + "переменная AlphaRef: " + AlphaRef.GetObject().GetName());
Прежде всего, переменной AlphaRef типа IMyCoVarGenIF в этом фрагменте кода присваивается ссылка на объект типа MyClass. Это вполне допустимая операция, поскольку в классе MyClass реализуется интерфейс IMyCoVarGenIF,причем и в том, и в другом в качестве аргумента типа указывается Alpha. Далее имяобъекта выводится на экран при вызове метода GetName() для объекта, возвращаемого методом GetObject(). И эта операция вполне допустима, поскольку Alpha — этои тип, возвращаемый методом GetName(), и обобщенный тип Т. После этого переменной AlphaRef присваивается ссылка на экземпляр объекта типа MyClass,что также допустимо, потому что класс Beta является производным от класса Alpha,а обобщенный тип Т — ковариантным в интерфейсе IMyCoVarGenIF. Если бы любоеиз этих условий не выполнялось, данная операция оказалась бы недопустимой.Ради большей наглядности примера вся рассмотренная выше последовательностьопераций собрана ниже в единую программу.// Продемонстрировать ковариантность в обобщенном интерфейсе.using System;// Этот обобщенный интерфейс поддерживает ковариантность.public interface IMyCoVarGenIF<out Т> { Т GetObject();}// Реализовать интерфейс IMyCoVarGenIF.class MyClass<T> : IMyCoVarGenIF<T> { T obj; public MyClass(T v) { obj = v; } public T GetObject() { return obj; }}// Создать простую иерархию классов.class Alpha { string name; public Alpha(string n) { name = n; } public string GetName() { return name; } // ...}class Beta : Alpha { public Beta(string n) : base(n) { } // ...}class VarianceDemo { static void Main() { // Создать ссылку из интерфейса IMyCoVarGenIF на объект типа MyClass<Alpha>. // Это вполне допустимо как при наличии ковариантности, так и без нее. IMyCoVarGenIF<Alpha> AlphaRef = new MyClass<Alpha>(new Alpha("Alpha #1")); Console.WriteLine("Имя объекта, на который ссылается переменная " + "AlphaRef: " + AlphaRef.GetObject().GetName()); // А теперь создать объект MyClass<Beta> и присвоить его // переменной AlphaRef. // *** Эта строка кода вполне допустима благодаря ковариантности. *** AlphaRef = new MyClass<Beta>(new Beta("Beta #1")); Console.WriteLine("Имя объекта, на который теперь ссылается переменная " + "AlphaRef: " + AlphaRef.GetObject().GetName()); }}
Результат выполнения этой программы выглядит следующим образом.Имя объекта, на который ссылается переменная AlphaRef: Alpha #1Имя объекта, на который теперь ссылается переменная AlphaRef: Beta #1
Следует особо подчеркнуть, что переменной AlphaRef можно присвоить ссылкуна объект типа MyClass благодаря только тому, что обобщенный тип Т указанкак ковариантный в интерфейсе IMyCoVarGenIF. Для того чтобы убедиться в этом,удалите ключевое слово out из объявления параметра обобщенного типа Т в интерфейсе IMyCoVarGenIF и попытайтесь скомпилировать данную программу еще раз.Компиляция завершится неудачно, поскольку строгая проверка на соответствие типовне разрешит теперь подобное присваивание.
Один обобщенный интерфейс может вполне наследовать от другого. Иными словами, обобщенный интерфейс с параметром ковариантного типа можно расширить,как показано ниже.public interface IMyCoVarGenIF2<out Т> : IMyCoVarGenIF<T> { // ...}
Обратите внимание на то, что ключевое слово out указано только в объявлении расширенного интерфейса. Указывать его в объявлении базового интерфейса не только ненужно, но и не допустимо. И последнее замечание: обобщенный тип Т допускается неуказывать как ковариантный в объявлении интерфейса IMyCoVarGenIF2. Но при этомисключается ковариантность, которую может обеспечить расширенный интерфейсIMyCoVarGetIF. Разумеется, возможность сделать интерфейс IMyCoVarGenIF2 инвариантным может потребоваться в некоторых случаях его применения.
На применение ковариантности накладываются некоторые ограничения. Ковариантность параметра типа может распространяться только на тип, возвращаемый методом. Следовательно, ключевое слово out нельзя применять в параметре типа, служащем для объявления параметра метода. Ковариантность оказывается пригоднойтолько для ссылочных типов. Ковариантный тип нельзя использовать в качестве ограничения в интерфейсном методе. Так, следующий интерфейс считается недопустимым.public interface IMyCoVarGenIF2<out Т> { void M<V>() where V:T; // Ошибка, ковариантный тип T нельзя // использовать как ограничение}Применение контравариантности в обобщенном интерфейсе
Применительно к обобщенному интерфейсу контравариантность служит средством, разрешающим методу использовать аргумент, тип которого относится к базовому классу, указанному в соответствующем параметре типа. В прошлом тип аргумента метода должен был в точности соответствовать параметру типа в силу строгойпроверки обобщений на соответствие типов. Контравариантность смягчает это строгоеправило таким образом, чтобы обеспечить типовую безопасность. Параметр контравариантного типа объявляется с помощью ключевого слова in, которое предваряет имяэтого параметра.