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

6.3Перегрузка индексаторов

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

Имейте в виду, что индексаторы могут быть перегружены в отдельном классе или структуре. То есть если имеет смысл позволить вызывающему коду обращаться к подэлементам с использованием числового индекса или строкового значения, в одном и том же типе можно определить несколько индексаторов. Например, если вы когда-либо программировали с применением ADO.NET (встроенный API-интерфейс .NET для доступа к базам данных), то вспомните, что тип DataSet поддерживает свойство по имени Tables, которое возвращает строго типизированную коллекцию DataTableCollection. В свою очередь, в DataTableCollection определены три индексатора для получения объектов DataTable — по порядковому номеру, по дружественным строковым именам и необязательному пространству имен.

Давайте рассмотрим пример использования перегрузки индексаторов:

using System;

namespace ConsoleApplication1

{

class MyArr

{

int[] arr;

public int Length;

public MyArr(int Size)

{

arr = new int[Size];

Length = Size;

}

public int this[int index]

{

get { return arr[index]; }

set { arr[index] = value; }

}

// Перегружаем индексатор

public int this[double index]

{ get { return arr[(int)Math.Round(index)]; }

set { arr[(int)Math.Round(index)] = value; }

}

}

class Program

{

static void Main(string[] args)

{

MyArr arr = new MyArr(5);

arr[0] = 5;

arr[1.235] = 12;

arr[2] = 3;

arr[3.045] = 18;

arr[3.9] = 1;

Console.WriteLine("Получившийся массив: ");

for (int i = 0; i < arr.Length; i++)

Console.Write("{0}\t", arr[i]);

Console.ReadLine();

}

}

}

Вывод программы:

Получившийся массив:

5 12 3 18 1

Представленный выше пример программы наглядно демонстрирует правомочность перегрузки индексаторов, но на практике она применяется нечасто. Как правило, индексаторы перегружаются для того, чтобы использовать объект определенного класса в качестве индекса, вычисляемого каким-то особым образом.

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

6.4Основы перегрузки операторов

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

// Операция + с целыми.

int а = 100, b = 240;

int с = а + b; //с теперь равно 340

Здесь нет ничего нового, но задумывались ли вы когда-нибудь о том, что одна и та же операция + может применяться к большинству встроенных типов данных C#? Например, рассмотрим такой код:

// Операция + со строками.

string si = "Hello";

string s2 = " world!";

string s3 = si + s2; // s3 теперь содержит "Hello world!"

По сути, функциональность операции + уникальным образом базируются на представленных типах данных (строках или целых в данном случае). Когда операция + применяется к числовым типам, мы получаем арифметическую сумму операндов. Однако когда та же операция применяется к строковым типам, получается конкатенация строк.

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

Операция C#

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

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

Этот набор унарных операций может быть перегружен

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

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

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

Эти операции сравнения могут быть перегружены. C# требует совместной перегрузки "подобных" операций (т.е. < и >, <= и >=, == и !=)

[]

Операция [] не может быть перегружена. Oднако, аналогичную функциональность предлагают индексаторы

()

Операция () не может быть перегружена. Однако ту же функциональность предоставляют специальные методы преобразования

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

Сокращенные операции присваивания не могут перегружаться; однако вы получаете их автоматически, перегружая соответствующую бинарную операцию

Перегрузка операторов тесно связана с перегрузкой методов. Для перегрузки оператора служит ключевое слово operator, определяющее операторный метод, который, в свою очередь, определяет действие оператора относительно своего класса. Существуют две формы операторных методов (operator): одна - для унарных операторов, другая - для бинарных. Ниже приведена общая форма для каждой разновидности этих методов:

// Общая форма перегрузки унарного оператора

public static возвращаемый_тип operator op(тип_параметра операнд)

{

// операции

}

// Общая форма перегрузки бинарного оператора

public static возвращаемый_тип operator ор(тип_параметра1 операнд1,

тип_параметра2 операнд2)

{

// операции

}

Здесь вместо ор подставляется перегружаемый оператор, например + или /, а возвращаемый_тип обозначает конкретный тип значения, возвращаемого указанной операцией. Это значение может быть любого типа, но зачастую оно указывается такого же типа, как и у класса, для которого перегружается оператор. Такая корреляция упрощает применение перегружаемых операторов в выражениях. Для унарных операторов операнд обозначает передаваемый операнд, а для бинарных операторов то же самое обозначают операнд1 и операнд2. Обратите внимание на то, что операторные методы должны иметь оба спецификатора типа - public и static.