Чтение онлайн

ЖАНРЫ

ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание

Троелсен Эндрю

Шрифт:

Исходный код. Проект SimpleIndexer размещен в подкаталоге, соответствующем главе 9.

Вариации индексатора для типа Garage

В своем текущем виде тип Gаrage определяет индексатор, который позволяет вызывающей стороне идентифицировать внутренние элементы, используя число-вое значение. Но это не является непременным требованием метода индексатора. Предположим, что объекты Car содержатся в System.Collections.Specialized. ListDictionary, а не в ArrayList. Поскольку типы ListDictionary позволяют доступ к содержащимся типам с помощью ключевых маркеров (таких как, например, строки),

можно создать новый индексатор Garage, подобный показанному ниже.

public class Garage: IEnumerable {

 private ListDictionary carDictionary = new ListDictionarу;

 // Этот индексатор возвращает соответствующий тип Car

 // на основе строкового индекса.

 public Car this[string name] {

get { return (Car)carDictionary[name]; }

set { carDictionary[name] = value; }

 }

 public int Length { get { return carDictionary.Count; } }

 public IEnumerator GetEnumerator { return carDictionary.GetEnumerator; }

}

Вызывающая сторона теперь может взаимодействовать с машинами внутри так, как показано ниже,

public class Program {

 static void Main(string[] args) {

Console:WriteLine("***** Забавы с индексаторами *****\n");

Garage carLot = new Garage;

// Добавление именованных машин в гараж.

carLot["FeeFee"] = new Car("FeeFee", 200, 0);

carLot["Clunker"] = new Car("Clunker", 90, 0);

carLot["Zippy"] = new Car("Zippy", 30, 0);

// Доступ к Zippy.

Car zippy = carLot["Zippy"];

Console.WriteLine("{0} едет со скоростью {1} км/ч", zippy.PetName, zippy.CurrSpeed);

Console.ReadLine;

 }

}

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

Исходный код. Проект StringIndexer размещен в подкаталоге, соответствующем главе 9.

Внутреннее представление индексаторов типов

Мы рассмотрели примеры метода индексатора в C#, и пришло время выяснить, как представляются индексаторы в терминах CIL. Если открыть числовой индексатор типа Garage, то будет видно, что компилятор C# создает свойство Item, которое сводится к подходящей паре методов get/set.

property instance class SimpleIndexer.Car Item(int32) {

 .get instance class SimpleIndexer.Car SimpleIndexer.Garage::get_Item(int32)

 .set instance void SimpleIndexer.Garage::set_Item(int32, class SimpleIndexer.Car)

} // end of property Garage::Item

Методы get_Item

и set_Item будут реализованы аналогично любому другому свойству .NET, например:

method public hidebysig specialname instance сlass SimpleIndexer.Car get_Item(int32 pos) cil managed {

 Code size 22 (0x16)

 .maxstack 2

 .locals init ([0] class SimpleIndexer.Car CSS1$0000)

 IL_0000: ldarg.0

 IL_0001: ldfld class [mscorlib] System.Collections.ArrayList SimpleIndexer.Garage::carArray

 IL_0006: ldarg.1

 IL_0007: callvirt instance object [mscorlib] Sysftem.Collections.ArrayList::get_Item(int32)

 IL_000c: castclass SimpleIndexer.Car

 IL_0011: stloc.0

 IL_0012: br.s IL_0014

 IL_0014: ldloc.0

 IL_0015: ret

} // end of method Garage::get_Item

Заключительные замечания об индексаторах

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

public class SameContainer {

 private int[,] my2DinArray = new int[10, 10];

 public int this[int row, int column] {/* прочитать или установить значение 2D-массива * /}

}

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

public interface IEstablishSubObjects {

 // Этот интерфейс определяет индексатор, возвращающий

 // строки на основе числового индекса.

 string this[int index] {get; set;}

}

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

Перегрузка операций

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

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

int а = 100;

int b = 240;

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

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

Поделиться с друзьями: