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

на главную - закладки

Жанры

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
должен вернуть тот же тип данных, который имеет индексатор.

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

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

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

Хозяйка забытой усадьбы

Воронцова Александра
5. Королевская охота
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Хозяйка забытой усадьбы

Ротмистр Гордеев

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

Лисья нора

Сакавич Нора
1. Всё ради игры
Фантастика:
боевая фантастика
8.80
рейтинг книги
Лисья нора

Запрети любить

Джейн Анна
1. Навсегда в моем сердце
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Запрети любить

Мастер 9

Чащин Валерий
9. Мастер
Фантастика:
боевая фантастика
попаданцы
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Мастер 9

Магия чистых душ 2

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.56
рейтинг книги
Магия чистых душ 2

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

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

Безумный Макс. Ротмистр Империи

Ланцов Михаил Алексеевич
2. Безумный Макс
Фантастика:
героическая фантастика
альтернативная история
4.67
рейтинг книги
Безумный Макс. Ротмистр Империи

Возрождение Феникса. Том 2

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

Ты - наша

Зайцева Мария
1. Наша
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Ты - наша

(не) Желанная тень его Высочества

Ловиз Мия
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
(не) Желанная тень его Высочества

Господин моих ночей (Дилогия)

Ардова Алиса
Маги Лагора
Любовные романы:
любовно-фантастические романы
6.14
рейтинг книги
Господин моих ночей (Дилогия)

Возвышение Меркурия. Книга 12

Кронос Александр
12. Меркурий
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 12