Полное руководство. С# 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] для удаления материала
Этот код выдает следующий результат.2 4 6 8 1013.4 15.4 17.4 19.4 21.40,0,0 2,2,2 4,4,4 6,6,6 8,8,8
В данном примере кода имеется ряд любопытных моментов. Прежде всего обратите внимание на объявление интерфейса ISeries в следующей строке кода.public interface ISeries<T> {
Как упоминалось выше, для объявления обобщенного интерфейса используетсятакой же синтаксис, что и для объявления обобщенного класса.
А теперь обратите внимание на следующее объявление класса ByTwos, реализующего интерфейс Iseries.class ByTwos<T> : ISeries<T> {
Параметр типа Т указывается не только при объявлении класса ByTwos, но и приобъявлении интерфейса ISeries. И это очень важно. Ведь класс, реализующий обобщенный вариант интерфейса, сам должен быть обобщенным. Так, приведенное нижеобъявление недопустимо, поскольку параметр типа Т не определен.class ByTwos : ISeries<T> { // Неверно!
Аргумент типа, требующийся для интерфейса ISeries, должен быть передан классу ByTwos. В противном случае интерфейс никак не сможет получить аргумент типа.Далее переменные, хранящие текущее значение в последовательном ряду (val) иего начальное значение (start), объявляются как объекты обобщенного типа Т. После этого объявляется делегат IncByTwo. Этот делегат определяет форму метода, используемого для увеличения на два значения, хранящегося в объекте типа Т. Для тогочтобы в классе ByTwos могли обрабатываться данные любого типа, необходимо каким-то образом определить порядок увеличения на два значения каждого типа данных.Для этого конструктору класса ByTwos передается ссылка на метод, выполняющийувеличение на два. Эта ссылка хранится в переменной экземпляра делегата incr. Когда требуется сгенерировать следующий элемент в последовательном ряду, этот методвызывается с помощью делегата incr.
А теперь обратите внимание на класс ThreeD. В этом классе инкапсулируются координаты трехмерного пространства (X,Z,Y). Его назначение — продемонстрироватьобработку данных типа класса в классе ByTwos.
Далее в классе GenIntfDemo объявляются три метода увеличения на два для объектов типа int, double и ThreeD. Все эти методы передаются конструктору классаByTwos при создании объектов соответствующих типов. Обратите особое вниманиена приведенный ниже метод ThreeDPlusTwo().// Определить метод увеличения на два каждого// последующего значения координат объекта типа ThreeD.static ThreeD ThreeDPlusTwo(ThreeD v) { if(v==null) return new ThreeD(0, 0, 0); else return new ThreeD(v.x + 2, v.y + 2, v.z + 2);}
В этом методе сначала проверяется, содержит ли переменная экземпляра v пустоезначение (null). Если она содержит это значение, то метод возвращает новый объекттипа ThreeD со всеми обнуленными полями координат. Ведь дело в том, что переменной v по умолчанию присваивается значение типа default(Т) в конструкторе классаByTwos. Это значение оказывается по умолчанию нулевым для типов значений и пустым для типов ссылок на объекты. Поэтому если предварительно не был вызван метод SetStart(), то перед первым увеличением на два переменная v будет содержатьпустое значение вместо ссылки на объект. Это означает, что для первого увеличения надва требуется новый объект.
На параметр типа в обобщенном интерфейсе могут накладываться ограничениятаким же образом, как и в обобщенном классе. В качестве примера ниже приведенвариант объявления интерфейса ISeries с ограничением на использование толькоссылочных типов.public interface ISeries<T> where T : class {
Если реализуется именно такой вариант интерфейса ISeries, в реализующемего классе следует указать то же самое ограничение на параметр типа Т, как показанониже.class ByTwos<T> : ISeries<T> where T : class {
В силу ограничения ссылочного типа этот вариант интерфейса ISeries нельзяприменять к типам значений. Поэтому если реализовать его в рассматриваемом здесьпримере программы, то допустимым окажется только объявление ByTwos,но не объявления ByTwos и ByTwos.Сравнение экземпляров параметра типа
Иногда возникает потребность сравнить два экземпляра параметра типа. Допустим, что требуется написать обобщенный метод IsIn(), возвращающий логическоезначение true, если в массиве содержится некоторое значение. Для этой цели сначаламожно попробовать сделать следующее.// Не годится!public static bool IsIn<T>(T what, T[] obs) { foreach(T v in obs) if(v == what) // Ошибка! return true; return false;}
К сожалению, эта попытка не пройдет. Ведь параметр Т относится к обобщенномутипу, и поэтому компилятору не удастся выяснить, как сравнивать два объекта. Требуется ли для этого поразрядное сравнение или же только сравнение отдельных полей?А возможно, сравнение ссылок? Вряд ли компилятор сможет найти ответы на эти вопросы. Правда, из этого положения все же имеется выход.
Для сравнения двух объектов параметра обобщенного типа они должны реализовывать интерфейс IComparable или IComparable и/или интерфейс IEquatable.В обоих вариантах интерфейса IComparable для этой цели определен методCompareTo(), а в интерфейсе IEquatable — метод Equals(). Разновидностиинтерфейса IComparable предназначены для применения в тех случаях, когда требуется определить относительный порядок следования двух объектов. А интерфейсIEquatable служит для определения равенства двух объектов. Все эти интерфейсыопределены в пространстве имен System и реализованы во встроенных в C# типах данных, включая int, string и double. Но их нетрудно реализовать и для собственныхсоздаваемых классов. Итак, начнем с обобщенного интерфейса IEquatable.
Интерфейс IEquatable объявляется следующим образом.public interface IEquatable<T>
Сравниваемый тип данных передается ему в качестве аргумента типа Т. В этом интерфейсе определяется метод Equals(), как показано ниже.bool Equals(Т other)
В этом методе сравниваются взывающий объект и другой объект, определяемыйпараметром other. В итоге возвращается логическое значение true, если оба объектаравны, а иначе — логическое значение false.
В ходе реализации интерфейса IEquatable обычно требуется также переопределять методы GetHashCode() и Equals(Object), определенные в классе Object,чтобы они оказались совместимыми с конкретной реализацией метода Equals().Ниже приведен пример программы, в которой демонстрируется исправленный вариант упоминавшегося ранее метода IsIn().// Требуется обобщенный интерфейс IEquatable<T>.public static bool IsIn<T>(T what, T[] obs) where T : IEquatable<T> { foreach(T v in obs) if(v.Equals(what)) // Применяется метод Equals(). return true; return false;}
Обратите внимание в приведенном выше примере на применение следующегоограничения.where Т : IEquatable<T>
Это ограничение гарантирует, что только те типы, в которых реализован интерфейсIEquatable, являются действительными аргументами типа для метода IsIn(). Внутри этого метода применяется метод Equals(), который определяет равенство одногообъекта другому.
Для определения относительного порядка следования двух элементов применяетсяинтерфейс IComparable. У этого интерфейса имеются две формы: обобщенная и необобщенная. Обобщенная форма данного интерфейса обладает преимуществом обеспечения типовой безопасности, и поэтому мы рассмотрим здесь именно ее. Обобщенный интерфейс IComparable объявляется следующим образом.public interface IComparable<T>
Сравниваемый тип данных передается ему в качестве аргумента типа Т. В этом интерфейсе определяется метод CompareTo(), как показано ниже.int CompareTo(Т other)
В этом методе сравниваются вызывающий объект и другой объект, определяемыйпараметром other. В итоге возвращается нуль, если вызывающий объект оказываетсябольше, чем объект other; и отрицательное значение, если вызывающий объект оказывается меньше, чем объект other.
Для того чтобы воспользоваться методом CompareTo(), необходимо указать ограничение, которое требуется наложить на аргумент типа для реализации обобщенногоинтерфейса IComparable. А затем достаточно вызвать метод CompareTo(), чтобысравнить два экземпляра параметра типа.