Чтение онлайн

на главную

Жанры

C# для профессионалов. Том II

Ватсон Карли

Шрифт:

class MyClass {

 public readonly int MyConstInst;

 MyClass {

// определяет и инициализирует здесь MyConstInst

Если поле в C# объявлено как

readonly
, то ему можно присвоить значение только в конструкторе.

Перезагрузка операторов

Перезагрузка операторов происходит в C# и в C++ аналогично, но существуют небольшие различия. Например, C++ допускает перезагрузку большинства своих операторов. C# имеет больше ограничений. Для многих составных операторов C# автоматически определяет значение оператора из значений составляющих операторов, т.е. там, где C++ допускает прямую перезагрузку. Например, в C++ перезагружается

+
и отдельно
+=
.
В C# можно перезагрузить только
+
. Компилятор всегда будет использовать перезагруженную версию
+
, чтобы автоматически определить значение
+=
для этого класса или структуры.

Следующие операторы могут перезагружаться в C# также, так и в C++:

□ Бинарные арифметические операторы

+
,
,
*
,
/
,
%

□ Унарные операторы

++
и 
– -
(только префиксная форма)

□ Операторы сравнения

!=
,
==
,
<
,
<=
,
>=

□ Побитовые операторы

&
,
|
,
~
,
^
!

□ Булевы значения

true
и
false

Следующие операторы, перезагружаемые в C++, нельзя перезагружать в C#.

□ Арифметические операторы присваивания

*=
,
/=
,
+=
,
– =
,
%=
. (Они определяются компилятором из соответствующих арифметических операторов и оператора присваивания, который не может перезагружаться.) Постфиксные операторы увеличения на единицу. Они определяются компилятором из перезагруженных версий соответствующих префиксных операторов. (Реализуются с помощью вызова соответствующей перезагруженной версии префиксного оператора, но возвращают первоначальное значение операнда вместо нового значения.)

□ Операторы побитового присваивания

&=
,
|
=,
^=
,
>>=
и
<<=
.

□ Булевы операторы

&&
,
||
. (Они определяются компилятором из соответствующих побитовых операторов.)

□ Оператор присваивания

=
. Значение этого оператора в C# фиксировано.

Существует также ограничение в том, что операторы сравнения должны перезагружаться парами, другими словами, при перезагрузке

==
необходимо перезагрузить также
!=
и наоборот. Аналогично, если перезагружается один из операторов
<
и
<=
, то необходимо перезагрузить оба оператора и так же для
>
и
>=
. Причина этого состоит в необходимости обеспечения согласованной поддержки для любых типов данных базы данных, которые могут иметь значение
null
и для которых поэтому, например,
==
не обязательно имеет результат, противоположный
!=
.

После определения того, что оператор, который требуется перезагрузить, является таким, который можно перезагрузить в C#, синтаксис для реального определения перезагруженной версии значительно проще, чем соответствующий синтаксис в C++. Единственный момент, о котором необходимо помнить при перегрузке операторов C#, состоит в том, что они всегда должны объявляться как статические члены класса. Это противоположно ситуации в C++, где можно определить свои операторы либо как статические члены класса, как член экземпляра класса (но беря на один параметр меньше), либо как функцию, которая не является членом класса вообще.

Причина того, что определение перезагруженных версий операторов настолько проще в C#, не имеет на самом деле ничего общего с самими перезагруженными версиями операторов. Это связано со способом, которым осуществляется управление памятью в C#. Определение перезагруженных версий операторов в C++ является областью, которая заполнена ловушками, Рассмотрим, например, попытку перезагрузить оператор

сложения для класса в C++. (Предполагается для этого,
что
CMyClass имеет член 
x
и сложение экземпляров означает сложение членов
x
.). Код может выглядеть следующим образом (предполагается, что перезагруженная версия является явной вставкой кода):

static CMyClass operator+(const CMyClass &lhs, const CMyClass &rhs) {

 CMyClass Result;

 Result.x = lhs.x + rhs.x;

 return Result;

}

Отметим, что оба параметра объявлены как

const
и передаются по ссылке, чтобы обеспечить оптимальную производительность. Это само по себе не слишком плохо. Однако теперь для возвращения результата, необходимо создать временный экземпляр
CMyClass
внутри перезагруженной версии оператора. Конечная инструкция
return Result
выглядит безопасной, но она будет компилироваться только в том случае, если доступен оператор присваивания для копирования
Result
из функции.

Это само по себе является нетривиальной задачей, так как если ссылки используются неправильно при определении, то очень легко случайно определить ссылку, которая рекурсивно вызывает себя, пока не будет получено переполнение стека. Перезагрузка операторов в C++ является задачей для опытных программистов. Нетрудно видеть, почему компания Microsoft решила сделать некоторые операторы неперезагружаемыми в C#.

В C# практика будет другой. Здесь нет необходимости явно передавать по ссылке, так как классы C# являются ссылочными переменными в любом случае (а для структур передача по ссылке снижает производительность). И возвращение значения является легкой задачей. Будет ли это класс или структура, надо просто вернуть значение временного результата, а компилятор C# гарантирует, что в результате будут скопированы либо поля-члены (для типов данных значений), либо адреса (для ссылочных типов). Единственный недостаток заключается в том, что нельзя использовать ключевое слово

const
, чтобы получить дополнительную проверку компилятора, которая определяет, изменяет или нет перезагруженная версия оператора параметры класса. Также C# не предоставляет улучшения производительности подставляемых функций, как происходит в C++.

static MyClass operator+(MyClass lhs, CMyClass rhs) {

 MyClassResult = new MyClass;

 Result.x = lhs.x + rhs.x;

 return Result;

}

Индексаторы

C# cтрого не разрешает перезагружать

[]
. Однако он позволяет определить так называемые индексаторы (indexer) класса, что обеспечивает такой же результат.

Синтаксис определении индексатора очень похож на синтаксис свойства. Предположим, что необходимо использовать экземпляры

MyClass
как массив, где каждый элемент индексируется с помощью
int
и возвращает
long
. Тогда можно сделать следующую запись:

class MyClass {

 public long this[int x] {

get {

// код для получения элемента

}

set {

// код для задания элемента, например X = value;

}

 }

 // и т.д.

Код внутри блока

get
выполняется всякий раз, когда
Mine[x]
стоит с правой стороны выражения (при условии, что выражение
Mine
является экземпляром
MyClass
и 
x
будет
int
), в то время как
блок
set выполняется только тогда, когда
Mine[x]
указывается с левой стороны выражения. Блок
set
ничего не может вернуть и использует ключевое слово
value
для указания величины, которая появится с правой стороны выражения. Блок
get
должен вернуть тот же тип данных, который имеет индексатор.

Поделиться:
Популярные книги

Авиатор: назад в СССР 12+1

Дорин Михаил
13. Покоряя небо
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Авиатор: назад в СССР 12+1

Третий

INDIGO
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий

В зоне особого внимания

Иванов Дмитрий
12. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
В зоне особого внимания

Кровавая весна

Михайлов Дем Алексеевич
6. Изгой
Фантастика:
фэнтези
9.36
рейтинг книги
Кровавая весна

Неудержимый. Книга XVIII

Боярский Андрей
18. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга XVIII

Вперед в прошлое!

Ратманов Денис
1. Вперед в прошлое
Фантастика:
попаданцы
5.00
рейтинг книги
Вперед в прошлое!

Начальник милиции. Книга 3

Дамиров Рафаэль
3. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции. Книга 3

Не грози Дубровскому!

Панарин Антон
1. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому!

Свадьба по приказу, или Моя непокорная княжна

Чернованова Валерия Михайловна
Любовные романы:
любовно-фантастические романы
5.57
рейтинг книги
Свадьба по приказу, или Моя непокорная княжна

Муж на сдачу

Зика Натаэль
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Муж на сдачу

Кодекс Крови. Книга I

Борзых М.
1. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга I

Польская партия

Ланцов Михаил Алексеевич
3. Фрунзе
Фантастика:
попаданцы
альтернативная история
5.25
рейтинг книги
Польская партия

Лорд Системы

Токсик Саша
1. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
4.00
рейтинг книги
Лорд Системы

Газлайтер. Том 2

Володин Григорий
2. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 2