C#. Урок 8. Перегрузка операторов, индексаторы

Уроки для опытных   17 февраля 2013  Автор статьи:  

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

В языке C# имеется возможность перегружать существующие унарные и бинарные операторы, рассмотренные в «Уроке 4». Это осуществляется через введение статически метотдов с помощью ключевого слова operator. Важно отметить, что есть возможность перегрузить только уже существующий оператор, нельзя придумать свой. Рассмотрим перегрузку на примере класса Vector.

public class Vector
{
public double X { get; set; }
pubcic double Y { get; set; }
}
public static Vector operator +(Vector vector1, Vector vector2)
{
return new Vector(vector1.X + vector1.X, vector2.Y + vector2.Y);
}
public static Vector operator -(Vector vector1, Vector vector2)
{
return new Vector(vector1.X - vector1.X, vector2.Y - vector2.Y);
}
public static Vector operator ++(Vector vector1)
{
return new Vector(vector1.X + 1, vector1.Y + 1);
}

В данном случае мы реализовали привычные операции сложения-вычитания векторов через перегрузку операторов «+» и «-«. Однако стоит учесть, что при перегрузке унарного оператора «++» тип возвращаемого значения должен совпадать (непонятно как интерпретировать запись vector++; — если тип возвращаемого значения стоит string?).
Имеются два ключевых слова implicit и explicit для преобразования. Рассмотрим их действие также на примере векторов. Как известно, можно рассматривать n-мерную систему координат, а значит и n-мерный вектор. Реализуем преобразование Vector2D в Vector3D следующим образом (очевидно, что Vector2D содержит 2 компоненты, Vector3D — 3, для которых должны присутствовать соответствующие поля в классах):

public static implicit operator Vector3D(Vector2D v)
{
return new Vector3D
{
X = v.X,
Y = v.Y,
Z = 0
};
}
...
Vector2D v2 = new Vector2D();
Vector3D v3 = v2;

То есть ключевое слово imlpicit допускает преобразование только без потери точности. Обратное преобразование:

public static explicit operator Vector2D(Vector3D v)
{
return new Vector2D
{
X = v.X,
Y = v.Y
};
}
...
Vector3D v3 = new Vector3D();
Vector2D v2 = (Vector2D)v3;

В этом случае оно возможно только в явном виде, так как присутствует утрата части данных (аналогично с int и double — из int в double можно неявно, а обратно только явно).
Также рассмотрим индексаторы — специальный механизм классов, структур, который позволяет обращаться к ним как к массивам. Это служит для инкапсуляции массива или коллекции под оболочкой класса. Работает это таким образом:

public class My
{
private int[] arr = new int[100];
// возможна введение многомерного индексатора
// public int this[int index1, ... , int indexN]
public int this[int index]
{
get { return arr[index]; }
private set { arr[index] = value; }
}
}
...
Console.WriteLine(My[50]);

Научиться программировать

  • на Delphi

  • на Java

  • на C++