В С# предусмотрены средства для создания пользовательских классов-контейнеров, к внутренним элементам которых можно обращаться при помощи того же оператора индекса, что и к элементам обычного массива встроенных типов. Метод, который обеспечивает такую возможность, получил название индексатора (indexer).
public class CarApp { public static void Main() { Cars carLot = new Cars(); carLot[0] = new Car("FeeFee, 200, 0); carLot[1] = new Car("BClunker, 90, 0); carLot[2] = new Car("Zippy, 30, 0): for(int i = 0; i < 3: i++) { Console.WriteLine("Car number {0}:", i);
Console.WriteLine("Name: {0} ", carLot[i].PetName); Console.WriteLine("Max speed: { 0 } ", carLot[i].MaxSpeed); }
В простейшем виде индексатор создается при помощи синтаксиса this[].
public Car this[int pos] { get { if (pos 10) throw new IndexOutOfRangeExceptlon("Out of range!"); else return (carArray[pos]): } set { carArray[pos] = value: } }
За исключением применения ключевого слова t h i s, индексатор ничем не отличается от обычного объявления свойства С#. Обратите внимание, что индексатор не обеспечивает никаких характерных для массивов С# возможностей, не считая применения оператора индекса. Например, мы не сможем воспользоваться имеющимся у каждого массива свойством Length: Console. WriteLine("Cars in stock: {0}", carLot. Length);
Язык С# позволяет создавать пользовательские классы и структуры, которые будут реагировать по-своему (как мы определим) на встроенные операторы, например на оператор сложения +. Этот прием называется перегрузкой операторов. Рассматривать перегрузку операторов мы будем на примере класса Point.
public class Point { private int x, y; public Point() {} public Point(int xPos, int yPos) { x = xPos; у = yPos: } public override string ToString() { return "X pas: " +this.x + "Y pos: " + this.y: }
public static int Main(string[] args) { Point ptOne = new Point(100, 100); Point ptTwo = new Point(40, 40); Point bigPoint = ptOne + ptTwo; Console. WrlteLine( "Here is the big point: {0}, bigPoint.ToString()); return 0; }
Чтобы приведенный выше код заработал, осталось переопределить оператор +. В С# для этого можно использовать ключевое слово operator. Обратите внимание, что его можно использовать только вместе с ключевым словом static:
public class Point { private int x, y; public Point(){}: public Point (int xPos, int yPos) { x = xPos; у = yPos; } // Перегружаем оператор сложения public static Point operator + (Point p1, Point p2) { Point newPoint = new Point(p1.x + p2.x, p1. у + p2.y); return newPoint; }
В С# часто возникает необходимость замещать метод System.Object.Equals(), чтобы можно было выполнять сравнения структурных типов. Помимо замещения методов Equals() и GetHashCode(), скорее всего, потребуется заместить также и операторы равенства (= = и !=).
public static bool operator ==(Point p1, Point p2) { return pl.Equals(p2); } public static bool operator !=(Point p1, Point p2); { return !p1.Equals(p2); }
Обратите внимание, что для перегрузки операторов равенства мы просто передаем выполнение всей необходимой работы замещенному методу Equals(). Теперь, если нам потребуется использовать обновленный класс Point в нашей программе, мы можем сделать это следующим образом:
// Применяем перегруженные операторы равенства public static int Main(string[] args) { If (ptOne = = ptTwo) Console.WriteLine("Same values! "); else Console. WriteLine("Nope. different values"); If (ptOne != ptTwo) Console.WriteLine( "These are not equal"); else Console.WriteLine("Same values!"); }
Еще один момент, который необходимо обязательно отметить, С# не позволит вам перегрузить оператор = = без перегрузки оператора ! = или наоборот.
Как и в случае с операторами равенства, С# позволяет производить перегрузку операторов срав- нения только парами. Первая пара это операторы, а вторая =.
public class Car : IComparable public int CompareTo(object o) { Car temp = (Car)o; if (this.CarID > temp.CarID) return 1; if (this.CarID < temp.CarID) return -1; else return 0; } public static bool operator < (Car c1, Car c2) { IComparable itfComp = (IComparable)c1; return (itfComp. CompareTo(c2) < 0); }
public static bool operator > (Car c1, Car c2) { (Comparable itfComp = (IComparable)cl; return (itfComp. CompareTo(c2) > 0); } public static bool operator = 0); }