Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Теоретический_курс.doc
Скачиваний:
36
Добавлен:
10.11.2019
Размер:
7.68 Mб
Скачать

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

Поведение операторов для пользовательских классов и структур можно изменить. Такой процесс называется перегрузкой операторов.

В C# пользовательские типы могут перегружать операторы путём определения функций статических членов с помощью ключевого слова operator. Не все операторы могут быть перегружены, а для некоторых операторов есть ограничения:

Операторы

Возможность перегрузки

+, -, !, ~, ++, --, true, false

Эти унарные операторы можно перегрузить

+, -, *, /, %, &, |, ^, <<, >>

Эти бинарные операторы нельзя перегрузить

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

Операторы сравнения можно перегрузить

&&, ||

Условные логические операторы нельзя перегрузить, но они вычисляются с помощью операторов & и |, допускающих перегрузку

[]

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

()

Оператор приведения нельзя перегрузить, но можно определить новые операторы преобразования (explicit и implicit)

+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=

Операторы присвоения нельзя перегрузить, но, например, += вычисляется с помощью +, допускающего перегрузку.

=, ., ?:, ->, new, is, sizeof, typeof

Эти операторы нельзя перегрузить

Операторы сравнения можно перегружать, но только парами: если перегружен оператор ==, то != также должен быть перегружен. Обратный принцип также действителен и действует для операторов < и >, а также для <= и >=.

Для перегрузки оператора в пользовательском классе нужно создать метод в классе с правильной сигнатурой. Метод нужно назвать «operator X», где Xимя или символ перегружаемого оператора. Унарные операторы имеют один параметр, а бинарные — два. В каждом случае один параметр должен быть такого же типа, как класс или структура, объявившие оператор, как показано в следующем примере:

public static Complex operator +(Complex c1, Complex c2)

15. Операторы преобразования

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

class SampleClass

{

public static explicit operator SampleClass(int i)

{

SampleClass temp = new SampleClass();

// Код для преобразования из int в SampleClass...

return temp;

}

}

Операторы преобразования обладают следующими свойствами:

  • Преобразования, определенные как implicit, выполняются автоматически, если это требуется.

  • Для выполнения преобразований, определенных как explicit, требуется вызов операции приведения.

  • Все преобразования должны быть объявлены как static.

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

В этом примере используется оператор явного преобразования. Этот оператор преобразует тип значения Byte в тип значения Digit. Поскольку в тип Digit могут быть преобразованы не все значения типа Byte, преобразование выполняется явным образом, что означает использование операции приведения, как показано в методе Main:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace LC_Console

{

struct Digit

{

byte value;

public Digit(byte value) // Конструктор

{

if (value > 9)

{

throw new System.ArgumentException();

}

this.value = value;

}

public static explicit operator Digit(Byte b) // Явное преобразование Byte в Digit

{

Digit d = new Digit(b); // Преобразование

Console.WriteLine("Преобразование прошло");

Console.WriteLine("Для продолжение нажмите любую клавишу . . . ");

Console.ReadKey();

return d;

}

}

class TestExplicitConversion

{

static void Main()

{

try

{

byte b = 3;

Digit d = (Digit)b; // Преобразование

}

catch (System.Exception e)

{

Console.WriteLine("Поймали исключение: {0}", e);

}

}

}

}

/* Выведет:

* Преобразование прошло

* Для продолжение нажмите любую клавишу . . .

*/

В этом примере демонстрируется неявное преобразование, в котором определяется оператор преобразования, выполняющий операцию, обратную описанной в предыдущем примере: преобразование значения типа Digit к целочисленному типу Byte. Поскольку к типу Byte можно преобразовать любое значение типа Digit, нет нужды делать преобразование явным для пользователя:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace LC_Console

{

struct Digit

{

byte value;

public Digit(Byte value)

{

if (value > 9)

{

throw new System.ArgumentException();

}

this.value = value;

}

public static implicit operator byte(Digit d) // Неявное преобразование Digit в Byte

{

Console.WriteLine("Преобразование прошло");

Console.WriteLine("Для продолжение нажмите любую клавишу . . . ");

Console.ReadKey();

return d.value; // Неявное преобразование

}

}

class TestImplicitConversion

{

static void Main()

{

Digit d = new Digit(3);

byte b = d; // Неявное преобразование

}

}

}

/* Выведет:

* Преобразование прошло

* Для продолжение нажмите любую клавишу . . .

*/