- Автор темы
- #1
Перегрузка операторов
Какое знакомый мотив...
Перегрузка операторов в C# несколько отличается от перегрузки операторов в C++. Давайте разбираться с нововведениями (рассматриваем, естественно, только отличия).
*****
Все перегруженные операторы должны быть открытыми статическими функциями класса. Следовательно, унарные операторы будут иметь один параметр, а бинарные - два.
*****
Унарные операторы
Можно перегружать следующие унарные операторы: +, -, !, ~, ++, --, true, false
Как уже оговаривалось выше, перегруженные унарные операторы должны иметь один параметр. Этот параметр должен быть типа класса, в котором реализуется данная функция.
В отличие от C++ при перегрузке операторов инкремента (++) и декремента (--), невозможно определить где постфикс, а где префикс. Поэтому при перегрузке данных операторов определены оба случая сразу.
Перегрузка операторов true и false в основном применяется для логических типов, у которых следующие два выражения не эквивалентны:
Это характерно для типов данных SQL, обладающих неопределенным состоянием (не true и не false). В этом случае компилятор может использовать перегруженные операторы true и false для правильного вычисления результатов таких выражений (см. пример в MSDN). Эти операторы должны возвращать тип bool и перегружаться в паре (если перегружается один, то должен перегружаться и второй).
Бинарные операторы
Можно перегружать следующие бинарные операторы: +, -, *, /, %, &, |, ^, <<, >>
Для данных операторов справедливы следующие правила: один из двух параметров функции должен быть типа класса; если в классе перегружен оператор + (например), то оператор += перегружается автоматически (это справедливо для всех вышеперечисленных бинарных операторов).
*****
Операторы +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= напрямую перегружать нельзя.
*****
Операторы сравнения ==, !=, <, >, <=, >= всегда перегружаются парами: == и !=, < и >, <= и >=.
Чаще всего перегружаются операторы == и !=, так как по умолчанию они сравнивают не сами объекты, а ссылки на них (для ссылочных типов). В паре с этими операторами желательно перегрузить функцию Equals, которая наследуется из базового класса Object, чтобы их функциональность не различалась. Подробнее об этом вы можете узнать, изучив пример из следующего раздела.
Операторы && и || напрямую не перегружаются. Для их эмуляции можно перегрузить операторы & и | (см. пример в MSDN), которые для булевских значений возвращают также булевское значение.
Оператор [] не перегружается, вместо него можно использовать индексаторы.
Следующие операторы перегружаться не могут: =, ., ?:, ->, new, is, sizeof, typeof
Оператор () перегружаться не может, но вместо него можно определить собственные преобразования.
Неявные преобразования
Это преобразования, которые можно применять без приведения типов. Такие преобразования (желательно) не должны вызывать исключительных ситуаций и не допускать потерю информации.
Явные преобразования
Это преобразования, которые применяются с приведением типа. Такие преобразования могут вызывать исключительные ситуации и допускать потерю информации.
Пример на перегрузку явных и неявных преобразований
Какое знакомый мотив...
Перегрузка операторов в C# несколько отличается от перегрузки операторов в C++. Давайте разбираться с нововведениями (рассматриваем, естественно, только отличия).
*****
Все перегруженные операторы должны быть открытыми статическими функциями класса. Следовательно, унарные операторы будут иметь один параметр, а бинарные - два.
*****
Унарные операторы
Можно перегружать следующие унарные операторы: +, -, !, ~, ++, --, true, false
Как уже оговаривалось выше, перегруженные унарные операторы должны иметь один параметр. Этот параметр должен быть типа класса, в котором реализуется данная функция.
Код:
using System;
class SomeClass
{
int i;
public SomeClass(int value)
{
i = value;
}
public static int operator - (SomeClass s)
{
return -s.i;
}
}
class Test
{
static void Main()
{
SomeClass sc = new SomeClass(10);
Console.WriteLine(-sc);
}
}
В отличие от C++ при перегрузке операторов инкремента (++) и декремента (--), невозможно определить где постфикс, а где префикс. Поэтому при перегрузке данных операторов определены оба случая сразу.
Код:
using System;
class SomeClass
{
int i;
public SomeClass(int value)
{
i = value;
}
// Для операторов ++ и -- возвращаемое значение
// также должно быть типа класса
public static SomeClass operator ++ (SomeClass s)
{
++s.i;
return s;
}
public override string ToString()
{
return i.ToString();
}
}
class Test
{
static void Main()
{
SomeClass sc = new SomeClass(10);
Console.WriteLine(++sc);
Console.WriteLine(sc++);
}
}
Перегрузка операторов true и false в основном применяется для логических типов, у которых следующие два выражения не эквивалентны:
Код:
if(a == true)
if(! (a == false))
Это характерно для типов данных SQL, обладающих неопределенным состоянием (не true и не false). В этом случае компилятор может использовать перегруженные операторы true и false для правильного вычисления результатов таких выражений (см. пример в MSDN). Эти операторы должны возвращать тип bool и перегружаться в паре (если перегружается один, то должен перегружаться и второй).
Код:
using System;
class SomeClass
{
int i;
public SomeClass(int value)
{
i = value;
}
public override string ToString()
{
return i.ToString();
}
public static bool operator true(SomeClass s)
{
return s.i != 0;
}
public static bool operator false(SomeClass s)
{
return s.i == 0;
}
}
class Test
{
static void Main()
{
SomeClass sc = new SomeClass(10);
if(sc)
Console.WriteLine("yes");
else
Console.WriteLine("no");
}
}
Бинарные операторы
Можно перегружать следующие бинарные операторы: +, -, *, /, %, &, |, ^, <<, >>
Для данных операторов справедливы следующие правила: один из двух параметров функции должен быть типа класса; если в классе перегружен оператор + (например), то оператор += перегружается автоматически (это справедливо для всех вышеперечисленных бинарных операторов).
*****
Операторы +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= напрямую перегружать нельзя.
*****
Код:
using System;
class SomeClass
{
int i;
public SomeClass(int value)
{
i = value;
}
public override string ToString()
{
return i.ToString();
}
public static SomeClass operator + (SomeClass s, int ii)
{
s.i += ii;
return s;
}
}
class Test
{
static void Main()
{
SomeClass sc = new SomeClass(10);
Console.WriteLine(sc + 3);
sc += 2;
Console.WriteLine(sc);
}
}
Операторы сравнения ==, !=, <, >, <=, >= всегда перегружаются парами: == и !=, < и >, <= и >=.
Чаще всего перегружаются операторы == и !=, так как по умолчанию они сравнивают не сами объекты, а ссылки на них (для ссылочных типов). В паре с этими операторами желательно перегрузить функцию Equals, которая наследуется из базового класса Object, чтобы их функциональность не различалась. Подробнее об этом вы можете узнать, изучив пример из следующего раздела.
Операторы && и || напрямую не перегружаются. Для их эмуляции можно перегрузить операторы & и | (см. пример в MSDN), которые для булевских значений возвращают также булевское значение.
Оператор [] не перегружается, вместо него можно использовать индексаторы.
Следующие операторы перегружаться не могут: =, ., ?:, ->, new, is, sizeof, typeof
Оператор () перегружаться не может, но вместо него можно определить собственные преобразования.
Неявные преобразования
Это преобразования, которые можно применять без приведения типов. Такие преобразования (желательно) не должны вызывать исключительных ситуаций и не допускать потерю информации.
Явные преобразования
Это преобразования, которые применяются с приведением типа. Такие преобразования могут вызывать исключительные ситуации и допускать потерю информации.
Пример на перегрузку явных и неявных преобразований
Код:
using System;
class SomeClass
{
int i;
public SomeClass(int value)
{
i = value;
}
public override string ToString()
{
return i.ToString();
}
// Неявное преобразование из SomeClass в int
public static implicit operator int(SomeClass s)
{
return s.i;
}
// Явное преобразование из int в SomeClass
public static explicit operator SomeClass(int ii)
{
SomeClass s = new SomeClass(ii);
return s;
}
}
class Test
{
static void Main()
{
SomeClass sc = new SomeClass(10);
// Неявное преобразование
int i = sc;
Console.WriteLine(i);
// Явное преобразование
sc = (SomeClass)100;
Console.WriteLine(sc);
}
}