Эндрю Троелсен - ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
- Название:ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2007
- Город:Москва • Санкт-Петербург • Киев
- ISBN:ISBN 5-8459-1124-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Эндрю Троелсен - ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание краткое содержание
В этой книге содержится описание базовых принципов функционирования платформы .NET, системы типов .NET и различных инструментальных средств разработки, используемых при создании приложений .NET. Представлены базовые возможности языка программирования C# 2005, включая новые синтаксические конструкции, появившиеся с выходом .NET 2.0, а также синтаксис и семантика языка CIL. В книге рассматривается формат сборок .NET, библиотеки базовых классов .NET. файловый ввод-вывод, возможности удаленного доступа, конструкция приложений Windows Forms, доступ к базам данных с помощью ADO.NET, создание Web-приложений ASP.NET и Web-служб XML. Книга содержит множество примеров программного кода, призванного помочь читателю в освоении предлагаемого материала. Программный код примеров можно загрузить с Web-сайта издательства.
ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
public static explicit operator Square(Rectangle r) {…}
Здесь предполагается, что квадрат (который является геометрической фигурой с равными сторонами) можно получить на основе ширины прямоугольника. Поэтому вы можете превратить Rectangle (прямоугольник) в Square (квадрат) так.
static void Main(string args) {
Console.WriteLine("***** Забавы с преобразованиями *****\n");
// Создание прямоугольника 10 х 5.
Rectangle rect;
reсt.Width = 10;
rect.Height = 5;
Console.WriteLine("rect = {0}", rect);
// Преобразование прямоугольника в квадрат 10 х 10.
Square sq = (Square)rect ;
Console.WriteLine("sq = {0}", sq);
Console.ReadLine();
}
Наверное, от превращения прямоугольников в квадраты в рамках одного контекста не слишком много пользы, но предположим, что у нас есть функция, которая предполагает использование типов Square.
// Этот метод требует использования типа Square.
private static void DrawSquare(Square sq) {
sq.Draw();
}
Используя нашу операцию явного преобразования, мы можем передавать этой функции типы Square.
static void Main(string[] args) {
…
// Преобразование Rectangle в Square для вызова метода.
DrawSquare((Square)rect);
}
Варианты явного преобразования для типа Square
Теперь вы можете явно превращать прямоугольники в квадраты, но рассмотрим еще несколько вариантов явного преобразования. Поскольку у квадрата стороны равны, можно явно преобразовать System.Int32 в Square (длина стороны квадрата будет равна значению поступающего целого числа). Аналогично можно изменить определение Square, если требуется обеспечить преобразование из Square в System.Int32. Вот логика соответствующего вызова.
static void Main(string[] args) {
…
// Преобразование System.Int32 в Square.
Square sq2 = (Square)90;
Console.WriteLine("sq2 = {0}", sq2);
// Преобразование Square в System.Int32.
int side = (int)sq2;
Console.WriteLine("Длина стороны sq2 = {0}", side);
}
А вот как следует обновить определение типа Square.
public struct Square {
…
public static explicitoperator Square(int sideLength) {
Square newSq;
newSq.Length = sideLength;
return newSq;
}
public static explicitoperator int(Square s) { return s.Length; }
}
Выглядит немного странно, не так ли? Честно говоря, преобразование из Square в System.Int32 не является интуитивно очевидной (или полезной) операцией. Однако она демонстрирует одну очень важную особенность пользовательских подпрограмм преобразования; компилятору "все равно" из чего и во что вы преобразуете – важно, чтобы ваш программный код был синтаксически правильным. Так что, как в случае с перегрузкой операций, только из того, что вы можете создать операцию явного преобразования для данного типа, совсем не следует, что вы обязаны это делать. Как правило, этот подход оказывается наиболее полезным тогда, когда создаются типы структуры .NET, поскольку такие типы не могут использовать иерархии классического наследования (для которых соответствующие преобразования реализуются автоматически).
Определение подпрограмм неявного преобразования
До этого момента мы с вами создавали пользовательские операции явного преобразования. Но что можно сказать о следующем неявном преобразовании?
static void Main(string[] args) {
…
// Попытка выполнить неявное преобразование?
Square s3;
s3.Length = 83;
Rectangle rect2 = s3;
}
Как вы можете догадаться сами, этот программный код скомпилирован не будет, поскольку в нем не предлагается никакой подпрограммы неявного преобразования для типа Rectangle. Тут нас подстерегает "ловушка": в одном и том же типе нельзя определять явные и неявные функции преобразования, не отличающиеся по типу возвращаемого значения или по набору параметров. Может показаться, что это правило является слишком ограничивающим, но не следует забывать о том, что даже если тип определяет подпрограмму неявного преобразования, вызывающая сторона "имеет право" использовать синтаксис явного преобразования!
Запутались? Чтобы прояснить ситуацию, добавим в структуру Rectangle подпрограмму неявного преобразования, используя ключевое слово C# implicit (в следующем программном коде предполагается, что ширина результирующего Rectangle получается с помощью умножения стороны Square на 2).
public struct Rесtangle {
…
public static implicit operator Rectangle(Square s) {
Rectangle r;
r.Height = s.Length;
// Ширина нового прямоугольника равна
// удвоенной длине стороны квадрата.
r.Width = s.Length * 2;
}
}
С такими изменениями вы получаете возможность преобразовывать указанные типы так.
static void Main(string[] args) {
…
// Неявное преобразование: все OK!
Square s3;
s3.Length = 83;
Rectangle rect2 = s3;
Console.WriteLine("rect2 = {0}", rect2);
DrawSquare(s3);
// Синтаксис явного преобразования: тоже OK!
Square s4;
S4.Length = 3;
Rectangle rect3 = (Rectangle)s4;
Console.WriteLine("rect3 = {0}", rect3);
…
}
Снова подчеркнем, что допускается определение подпрограмм и явного, и неявного преобразования для одного и того же типа, но только если отличаются их сигнатуры. Поэтому мы можем обновить Square так, как показано ниже.
public struct Square {
…
// Можно вызывать как Square sq2 = (Square)90;
// или как Square sq2= 90;
public static implicit operator Square(int sideLength) {
Square newSq;
newSq.Length = sideLength;
return newSq;
// Должно вызываться как int side = (Square)mySquare;
public static explicit operator int(Square s) { return s.Length; }
}
}
Внутреннее представление пользовательских подпрограмм преобразования
Как и в случае перегруженных операций, те методы, которые обозначены ключевыми словами implicit или explicit, получают "специальные имена" в терминах CIL: op_Implicit и op_Explicit соответственно (рис. 9.2).

Рис. 9.2. Представление пользовательских подпрограмм преобразования в терминах CIL.
На этом мы завершаем обзор возможностей пользовательских подпрограмм преобразования. Как и в случае перегруженных операций, соответствующий синтаксис является лишь сокращённым вариантом определения "нормальных" членов-функций, и с этой точки зрения он не является обязательным.
Исходный код.Проект CustomConversions размещен в подкаталоге, соответствующем главе 9.
Ключевые слова C#, предназначенные для более сложных конструкций
Интервал:
Закладка: