Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
13
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

13.2.4Индексаторы интерфейса

Индексаторы интерфейса объявляются с использованием объявлений_индексаторов_интерфейса:

объявление_индексатора_интерфейса: атрибутынеобязательно newнеобязательно тип this [ список_формальных_параметров ] { методы_доступа_к_интерфейсу }

В объявлении индексатора интерфейса атрибуты, тип и список_формальных_параметров имеют такой же смысл, что и в объявлении индексатора класса (§10.9).

Методы доступа в объявлении индексатора интерфейса соответствуют методам доступа в объявлении индексатора класса (§10.9) за тем исключением, что тело метода доступа должно всегда быть точкой с запятой. Таким образом, методы доступа просто указывают, каким является индекс: доступным на чтение и запись, только на чтение или только на запись.

Все типы формальных параметров индексатора интерфейса должны быть безопасны при вводе. Кроме того, любой из типов формальных параметров out или ref также должен быть безопасным при выводе. Обратите внимание, что даже параметры out должны быть безопасными при вводе, согласно ограничению базовой платформы выполнения.

Тип индексатора интерфейса должен быть безопасным при выводе, если существует метод доступа get, а также безопасным при вводе, если существует метод доступа set.

13.2.5Доступ к членам интерфейса

Доступ к членам интерфейса осуществляется с использованием выражений доступа к членам (§7.6.4) и доступа к индексаторам (§7.6.6.2) в форме I.M и I[A], где I указывает тип интерфейса, M — метод, свойство или событие этого типа интерфейса, а A — список аргументов индексатора.

Для интерфейсов, которые наследуют строго от одного предка (каждый интерфейс в цепочке наследования имеет только один прямой базовый интерфейс или не имеет его вовсе), результаты применения правил поиска членов (§7.4), вызова методов (§7.6.5.1) и доступа к индексатору (§7.6.6.2) аналогичны результатам для классов и структур: производные члены скрывают соответствующие базовые члены с тем же именем или той же подписью. Однако в интерфейсах с множественным наследованием могут происходить неоднозначности, связанные с объявлением в двух (или более) базовых интерфейсах методов с одинаковыми именами или подписями. В данном разделе приводится несколько примеров подобных ситуаций. Во всех случаях для разрешения таких неоднозначностей можно использовать явное приведение типов.

В этом примере

interface IList { int Count { get; set; } }

interface ICounter { void Count(int i); }

interface IListCounter: IList, ICounter {}

class C { void Test(IListCounter x) { x.Count(1); // Error x.Count = 1; // Error ((IList)x).Count = 1; // Ok, invokes IList.Count.set ((ICounter)x).Count(1); // Ok, invokes ICounter.Count } }

выполнение первых двух операторов ведет к ошибкам при компилировании, поскольку поиск членов (§7.4) метода Count в интерфейсе IListCounter является неоднозначным. Как показано в этом примере, неоднозначность разрешается путем приведения переменной x к типу соответствующего базового интерфейса. Такое приведение не требует дополнительных затрат ресурсов во время выполнения — оно просто означает, что при компилировании экземпляр будет рассматриваться как находящийся на предыдущем уровне наследования.

В этом примере

interface IInteger { void Add(int i); }

interface IDouble { void Add(double d); }

interface INumber: IInteger, IDouble {}

class C { void Test(INumber n) { n.Add(1); // Invokes IInteger.Add n.Add(1.0); // Only IDouble.Add is applicable ((IInteger)n).Add(1); // Only IInteger.Add is a candidate ((IDouble)n).Add(1); // Only IDouble.Add is a candidate } }

при вызове метода n.Add(1) выбирается метод IInteger.Add в результате применения правил разрешения перегрузки, рассматриваемых в §7.5.3. Точно так же при вызове метода n.Add(1.0) выбирается метод IDouble.Add. Если вставлено явное приведение типов, кандидатом является только один метод, что позволяет избежать неоднозначности.

В этом примере

interface IBase { void F(int i); }

interface ILeft: IBase { new void F(int i); }

interface IRight: IBase { void G(); }

interface IDerived: ILeft, IRight {}

class A { void Test(IDerived d) { d.F(1); // Invokes ILeft.F ((IBase)d).F(1); // Invokes IBase.F ((ILeft)d).F(1); // Invokes ILeft.F ((IRight)d).F(1); // Invokes IBase.F } }

член IBase.F скрыт членом ILeft.F. В результате при вызове метода d.F(1) выбирается метод ILeft.F несмотря на то, что метод IBase.F не скрыт явным образом в пути доступа, идущем через интерфейс IRight.

Интуитивное правило скрытия членов в интерфейсах с множественным наследованием звучит так: если член скрыт в одном из путей доступа, он скрыт и во всех остальных путях доступа. Поскольку в пути доступа от IDerived через ILeft к IBase метод IBase.F скрыт, этот член также является скрытым в пути доступа от IDerived через IRight до IBase.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]