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

  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.

<p>Внутреннее представление индексаторов типов</p>

Мы рассмотрели примеры метода индексатора в 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

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

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

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: это перегрузка операций.

<p>Перегрузка операций</p>

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

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

int а = 100;

int b = 240;

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

Перейти на страницу:

Похожие книги