Полное руководство. С# 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] для удаления материала
Тем не менее с помощью операторов == и != можно проверить, содержит ли обнуляемый объект пустое значение. Например, следующая проверка вполне допустима идает истинный результат.if(upper == null) // ...
Если в логическом выражении участвуют два объекта типа bool?, то его результатможет иметь одно из трех следующих значений: true (истинное), false (ложное) илиnull (неопределенное). Ниже приведены результаты применения логических операторов & и | к объектам типа bool?.PQP | QP & Qtruenulltruenullfalsenullnullfalsenulltruetruenullnullfalsenullfalsenullnullnullnull
И наконец, если логический оператор ! применяется к значению типа bool?, которое является пустым (null), то результат этой операции будет неопределенным(null).Частичные типы
Начиная с версии 2.0, в C# появилась возможность разделять определение класса,структуры или интерфейса на две или более части с сохранением каждой из них в отдельном файле. Это делается с помощью контекстного ключевого слова partial. Всеэти части объединяются вместе во время компиляции программы.
Если модификатор partial используется для создания частичного типа, то онпринимает следующую общую форму:partial тип имя_типа { // ...
где имя_типа обозначает имя класса, структуры или интерфейса, разделяемого на части. Каждая часть получающегося частичного типа должна указываться вместе с модификатором partial.
Рассмотрим пример разделения простого класса, содержащего координаты XY, натри отдельных файла. Ниже приведено содержимое первого файла.
partial class XY { public XY(int a, int b) { X = a; Y = b; }}
Далее следует содержимое второго файла.partial class XY { public int X { get; set; }}
И наконец, содержимое третьего файла.partial class XY { public int Y { get; set; }}В приведенном ниже файле исходного текста программы демонстрируется применение класса XY.
// Продемонстрировать определения частичного класса.using System;
class Test { static void Main() { XY xy = new XY (1, 2); Console.WriteLine(xy.X + + xy.Y); }}Для того чтобы воспользоваться классом XY, необходимо включить в компиляцию все его файлы. Так, если файлы класса XY называются xy1.cs, ху2.cs и ху3.cs,а класс Test содержится в файле test.cs, то для его компиляции достаточно ввестив командной строке следующее.
csc test.cs xy1.cs xy2.cs хуЗ.csИ последнее замечание: в C# допускаются частичные обобщенные классы. Но параметры типа в объявлении каждого такого класса должны совпадать с теми, что указываются в остальных его частях.## Частичные методыКак пояснялось в предыдущем разделе, с помощью модификатора partial можно создать класс частичного типа. Начиная с версии 3.0, в C# появилась возможностьиспользовать этот модификатор и для создания частичного метода в элементе данныхчастичного типа. Частичный метод объявляется в одной его части, а реализуется в другой. Следовательно, с помощью модификатора partial можно отделить объявлениеметода от его реализации в частичном классе или структуре.Главная особенность частичного метода заключается в том, что его реализация нетребуется! Если частичный метод не реализуется в другой части класса или структуры,то все его вызовы молча игнорируются. Это дает возможность определить, но не востребовать дополнительные, хотя и не обязательные функции класса. Если эти функциине реализованы, то они просто игнорируются.Ниже приведена расширенная версия предыдущей программы, в которой создается частичный метод Show(). Этот метод вызывается другим методом, ShowXY(). Радиудобства все части класса XY представлены в одном файле, но они могут быть распределены по отдельным файлам, как было показано в предыдущем разделе.
// Продемонстрировать применение частичного метода.using System;
partial class XY { public XY(int a, int b) { X = a; Y = b; }// Объявить частичный метод.partial void Show();
}
partial class XY { public int X { get; set; }// Реализовать частичный метод.partial void Show() { Console.WriteLine("{0}, {1}", X, Y);}
}
partial class XY { public int Y { get; set; }// Вызвать частичный метод.public void ShowXY() { Show();}
}
class Test { static void Main() { XY xy = new XY(1, 2); xy.ShowXY(); }}Обратите внимание на то, что метод Show() объявляется в одной части класса XY,а реализуется в другой его части. В реализации этого метода выводятся значения координат X и Y. Это означает, что когда метод Show() вызывается из метода ShowXY(),то данный вызов действительно имеет конкретные последствия: вывод значенийкоординат X и Y. Но если закомментировать реализацию метода Show(), то его вызовиз метода ShowXY() ни к чему не приведет.Частичным методам присущ ряд следующих ограничений. Они должны возвращать значение типа void. У них не может быть модификаторов доступа и они не могутбыть виртуальными. В них нельзя также использовать параметры out.## Создание объектов динамического типаКак уже упоминалось не раз, начиная с главы 3, C# является строго типизированным языком программирования. Вообще говоря, это означает, что все операции проверяются во время компиляции на соответствие типов, и поэтому действия, не поддерживаемые конкретным типом, не подлежат компиляции. И хотя строгий контрольтипов дает немало преимуществ программирующему, помогая создавать устойчивыеи надежные программы, он может вызвать определенные осложнения в тех случаях,когда тип объекта остается неизвестным вплоть до времени выполнения. Нечто подобное может произойти при использовании рефлексии, доступе к COM-объекту илиже в том случае, если требуется возможность взаимодействия с таким динамическимязыком, как, например, IronPython. До появления версии C# 4.0 подобные ситуациибыли трудноразрешимы. Поэтому для выхода из столь затруднительного положенияв версии C# 4.0 был внедрен новый тип данных под названием dynamic.За одним важным исключением, тип dynamic очень похож на тип object, поскольку его можно использовать для ссылки на объект любого типа. А отличается онот типа object тем, что вся проверка объектов типа dynamic на соответствие типовоткладывает до времени выполнения, тогда как объекты типа object подлежат этойпроверке во время компиляции. Преимущество откладывания подобной проверки довремени выполнения состоит в том, что во время компиляции предполагается, чтообъект типа dynamic поддерживает любые операции, включая применение операторов, вызовы методов, доступ к полям и т.д. Это дает возможность скомпилировать кодбез ошибок. Конечно, если во время выполнения фактический тип, присваиваемыйобъекту, не поддерживает ту или иную операцию, то возникнет исключительная ситуация во время выполнения.В приведенном ниже примере программы применение типа dynamic демонстрируется на практике.
// Продемонстрировать применение типа dynamic.using System;using System.Globalization;
class DynDemo { static void Main() { // Объявить две динамические переменные. dynamic str; dynamic val; // Поддерживается неявное преобразование в динамические типы. // Поэтому следующие присваивания вполне допустимы. str = "Это строка"; val = 10; Console.WriteLine("Переменная str содержит: " + str); Console.WriteLine("Переменная val содержит: " + val + 'n'); str = str.ToUpper(CultureInfo.CurrentCulture); Console.WriteLine("Переменная str теперь содержит: " + str); val = val + 2; Console.WriteLine("Переменная val теперь содержит: " + val + 'n'); string str2 = str.ToLower(CultureInfo.CurrentCulture); Console.WriteLine("Переменная str2 содержит: " + str2); // Поддерживаются неявные преобразования из динамических типов. int х = val * 2; Console.WriteLine("Переменная x содержит: " + х);}
}Выполнение этой программы дает следующий результат.
Переменная str содержит: Это строкаПеременная val содержит: 10
Переменная str теперь содержит: ЭТО СТРОКАПеременная val теперь содержит: 12
Переменная str2 содержит: это строкаПеременная х содержит: 24Обратите внимание в этой программе на две переменные str и val, объявляемыес помощью типа dynamic. Это означает, что проверка на соответствие типов операцийс участием обеих переменных не будет произведена во время компиляции. В итогедля них оказывается пригодной любая операция. В данном случае для переменнойstr вызываются методы ToUpper() и ToLower() класса String, а переменная участвует в операциях сложения и умножения. И хотя все перечисленные выше действиясовместимы с типами объектов, присваиваемых обеим переменным в рассматриваемом здесь примере, компилятору об этом ничего не известно — он просто принимает.И это, конечно, упрощает программирование динамических процедур, хотя и допускает возможность появления ошибок в подобных действиях во время выполнения.В разбираемом здесь примере программа ведет себя "правильно" во время выполнения, поскольку объекты, присваиваемые упомянутым выше переменным, поддерживают действия, выполняемые в программе. В частности, переменной val присваивается целое значение, и поэтому она поддерживает такие целочисленные операции,как сложение. А переменной str присваивается символьная строка, и поэтому онаподдерживает строковые операции. Следует, однако, иметь в виду, что ответственностьза фактическую поддержку типом объекта, на который делается ссылка, всех операцийнад данными типа dynamic возлагается на самого программирующего. В противномслучае выполнение программы завершится аварийным сбоем.В приведенном выше примере обращает на себя внимание еще одно обстоятельство: переменной типа dynamic может быть присвоен любой тип ссылки на объектблагодаря неявному преобразованию любого типа в тип dynamic. Кроме того, типdynamic автоматически преобразуется в любой другой тип. Разумеется, если во времявыполнения такое преобразование окажется неправильным, то произойдет ошибкапри выполнении. Так, если добавить в конце рассматриваемой здесь программы следующую строку кода: