Полное руководство. С# 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] для удаления материала
Далее проанализируем приведенный ниже конструктор класса Test.public Test() { // Этот код работоспособен благодаря наложению ограничения new(). obj = new Т(); // создать объект типа Т}
В этом фрагменте кода создается объект типа Т, и ссылка на него присваиваетсяпеременной экземпляра obj. Такой код допустим только потому, что ограничениеnew() требует наличия конструктора. Для того чтобы убедиться в этом, попробуйтесначала удалить ограничение new(), а затем попытайтесь перекомпилировать программу. В итоге вы получите сообщение об ошибке во время компиляции.
В методе Main() получается экземпляр объекта типа Test, как показано ниже.Test<MyClass> х = new Test<MyClass>();
Обратите внимание на то, что аргументом типа в данном случае является классMyClass и что в этом классе определяется конструктор без параметров. Следовательно, этот класс допускается использовать в качестве аргумента типа для класса Test.Следует особо подчеркнуть, что в классе MyClass совсем не обязательно определятьконструктор без параметров явным образом. Его используемый по умолчанию конструктор вполне удовлетворяет накладываемому ограничению. Но если классу потребуются другие конструкторы, помимо конструктора без параметров, то придетсяобъявить явным образом и вариант без параметров.
Что касается применения ограничения new(), то следует обратить внимание натри других важных момента. Во-первых, его можно использовать вместе с другимиограничениями, но последним по порядку. Во-вторых, ограничение new() позволяетконструировать объект, используя только конструктор без параметров, — даже еслидоступны другие конструкторы. Иными словами, передавать аргументы конструкторупараметра типа не разрешается. И в-третьих, ограничение new() нельзя использоватьодновременно с ограничением типа значения, рассматриваемым далее.Ограничения ссылочного типа и типа значения
Два других ограничения позволяют указать на то, что аргумент, обозначающий тип,должен быть либо ссылочного типа, либо типа значения. Эти ограничения оказываются полезными в тех случаях, когда для обобщенного кода важно провести различиемежду ссылочным типом и типом значения. Ниже приведена общая форма ограничения ссылочного типа.where Т : class
В этой форме с оператором where ключевое слово class указывает на то, что аргумент Т должен быть ссылочного типа. Следовательно, всякая попытка использоватьтип значения, например int или bool, вместо Т приведет к ошибке во время компиляции.
Ниже приведена общая форма ограничения типа значения.where Т : struct
В этой форме ключевое слово struct указывает на то, что аргумент Т должен бытьтипа значения. (Напомним, что структуры относятся к типам значений.) Следовательно, всякая попытка использовать ссылочный тип, например string, вместо T приведетк ошибке во время компиляции. Но если имеются дополнительные ограничения, тов любом случае class или struct должно быть первым по порядку накладываемымограничением.
Ниже приведен пример, демонстрирующий наложение ограничения ссылочноготипа.// Продемонстрировать наложение ограничения ссылочного типа.using System;class MyClass { // ...}// Наложить ограничение ссылочного типа.class Test<T> where Т : class { Т obj; public Test() { // Следующий оператор допустим только потому, что // аргумент Т гарантированно относится к ссылочному // типу, что позволяет присваивать пустое значение. obj = null; } // ...}class ClassConstraintDemo { static void Main() { // Следующий код вполне допустим, поскольку MyClass является классом. Test<MyClass> х = new Test<MyClass>(); // Следующая строка кода содержит ошибку, поскольку // int относится к типу значения. // Test<int> у = new Test<int>(); }}
Обратите внимание на следующее объявление класса Test.class Test<T> where T : class {
Ограничение class требует, чтобы любой аргумент Т был ссылочного типа. В данном примере кода это необходимо для правильного выполнения операции присваивания в конструкторе класса Test.public Test() { // Следующий оператор допустим только потому, что // аргумент Т гарантированно относится к ссылочному // типу, что позволяет присваивать пустое значение. obj = null;}
В этом фрагменте кода переменной obj типа T присваивается пустое значение. Такое присваивание допустимо только для ссылочных типов. Как правило, пустое значение нельзя присвоить переменной типа значения. (Исключением из этого правилаявляется обнуляемый тип, который представляет собой специальный тип структуры,инкапсулирующий тип значения и допускающий пустое значение (null). Подробнееоб этом — в главе 20.) Следовательно, в отсутствие ограничения такое присваиваниебыло бы недопустимым, и код не подлежал бы компиляции. Это один из тех случаев,когда для обобщенного кода может оказаться очень важным различие между типамизначений и ссылочными типами.
Ограничение типа значения является дополнением ограничения ссылочного типа.Оно просто гарантирует, что любой аргумент, обозначающий тип, должен быть типазначения, в том числе struct и enum. (В данном случае обнуляемый тип не относитсяк типу значения.) Ниже приведен пример наложения ограничения типа значения.// Продемонстрировать наложение ограничения типа значения.using System;struct MyStruct { // ...}class MyClass { // ...}class Test<T> where T : struct { T obj; public Test(T x) { obj = x; } // ...}class ValueConstraintDemo { static void Main() { // Оба следующих объявления вполне допустимы. Test<MyStruct> х = new Test<MyStruct>(new MyStruct()); Test<int> у = new Test<int>(10); // А следующее объявление недопустимо! // Test<MyClass> z = new Test<MyClass>(new MyClass()); }}
В этом примере кода класс Test объявляется следующим образом.class Test<T> where Т : struct {
На параметр типа Т в классе Test накладывается ограничение struct, и поэтому к нему могут быть привязаны только аргументы типа значения. Это означает, чтообъявления Test и Test вполне допустимы, тогда как объявлениеTest недопустимо. Для того чтобы убедиться в этом, удалите символы комментария в начале последней строки приведенного выше кода и перекомпилируйтеего. В итоге вы получите сообщение об ошибке во время компиляции.Установление связи между двумя параметрами типа с помощью ограничения
Существует разновидность ограничения на базовый класс, позволяющая установитьсвязь между двумя параметрами типа. В качестве примера рассмотрим следующееобъявление обобщенного класса.class Gen<T; V> where V : T {
В этом объявлении оператор where уведомляет компилятор о том, что аргументтипа, привязанный к параметру типа V, должен быть таким же, как и аргумент типа,привязанный к параметру типа Т, или же наследовать от него. Если подобная связьотсутствует при объявлении объекта типа Gen, то во время компиляции возникнетошибка. Такое ограничение на параметр типа называется неприкрытым ограничениемтипа. В приведенном ниже примере демонстрируется наложение этого ограничения.// Установить связь между двумя параметрами типа.using System;class А { // ...}class В : А { // ...}// Здесь параметр типа V должен наследовать от параметра типа Т.class Gen<T, V> where V : T { // ...}class NakedConstraintDemo { static void Main() { // Это объявление вполне допустимо, поскольку // класс В наследует от класса А. GerKA, В> х = new Gen<A, В>(); // А это объявление недопустимо, поскольку // класс А не наследует от класса В. // Gen<B, А> у = new Gen<B, А>(); }}
Обратите внимание на то, что класс В наследует от класса А. Проанализируем далееоба объявления объектов класса Gen в методе Main(). Как следует из комментарияк первому объявлениюGen<A, В> х = new Gen<A, В>();
оно вполне допустимо, поскольку класс В наследует от класса А. Но второе объявление// Gen<B, А> у = new Gen<B, А>();
недопустимо, поскольку класс А не наследует от класса В.Применение нескольких ограничений
С параметром типа может быть связано несколько ограничений. В этом случаеограничения указываются списком через запятую. В этом списке первым должно бытьуказано ограничение class либо struct, если оно присутствует, или же ограничениена базовый класс, если оно накладывается. Указывать ограничения class или structодновременно с ограничением на базовый класс не разрешается. Далее по спискудолжно следовать ограничение на интерфейс, а последним по порядку — ограничениеnew(). Например, следующее объявление считается вполне допустимым.class Gen<T> where Т : MyClass, IMyInterface, new() { // ...