282
Глава.10 .Свойства
Если в справочной документации .NET Framework указано, что тип поддержи-
вает свойство
Item
, значит, данный тип поддерживает индексатор. Так, тип
System.
Collections.Generic.List
предлагает открытое экземплярное свойство
Item
,
которое является индексатором объекта
List
.
Программируя на C#, вы
никогда не увидите имя
Item
, поэтому выбор его
компилятором обычно не должен вызывать беспокойства. Однако если вы раз-
рабатываете индексатор для типа, который будет использоваться в программах,
написанных на других языках,
возможно, придется изменить имена методов до-
ступа индексатора (
get
и
set
). C# позволяет переименовать эти методы, применив
к индексатору пользовательский атрибут
System.Runtime.CompilerServices.
IndexerNameAttribute
. Пример:
using System;
using System.Runtime.CompilerServices;
public sealed class BitArray {
[IndexerName("Bit")]
public Boolean this[Int32 bitPos] {
// Здесь определен по крайней мере один метод доступа
}
}
Теперь компилятор сгенерирует вместо методов
get_Item
и
set_Item
методы
get_Bit
и
set_Bit
. Во время компиляции компилятор C# обнаруживает атрибут
IndexerName
,
который сообщает ему, какие имена следует присвоить методам
и метаданным свойств; сам по себе атрибут не включается в метаданные сборки
1
.
Приведу фрагмент кода на языке Visual Basic, демонстрирующий обращение
к индексатору, написанному на C#:
' Создать экземпляр типа BitArray
Dim ba as New BitArray(10)
' В Visual Basic индекс элемента массива задается в круглых скобках (),
' а не в квадратных [].
Console.WriteLine(ba(2)) " Выводит True или False
' Visual Basic также позволяет обращаться к индексатору по имени
Console.WriteLine(ba.Bit(2)) ' Выводит то же, что предыдущая строка
В C# в одном типе можно определять несколько индексаторов при условии,
что они получают разные наборы параметров. В
других языках программирова-
ния атрибут
IndexerName
позволяет задать несколько индексаторов с одинаковой
сигнатурой, поскольку их имена могут отличаться. Однако C# не допускает этого,
так как принятый в C# синтаксис не позволяет ссылаться на индексатор по имени,
1
По этой причине класс IndexerNameAttribute не входит в описанные в ECMA стандарты
CLI и языка C#.
283
Свойства.с.параметрами
а значит, компилятор не будет знать, на какой индексатор ссылаются. При попытке
компиляции следующего исходного текста на C#
компилятор выдает сообщение
об ошибке (ошибка CS0111: в классе
SomeType
уже определен член
this
с таким
же типом параметра):
error CS0111: Class 'SomeType' already defines a member called 'this' with the same
parameter types
Фрагмент кода, приводящий к выдаче этого сообщения:
using System;
using System.Runtime.CompilerServices;
public sealed class SomeType {
// Определяем метод доступа get_Item
public Int32 this[Boolean b] {
get { return 0; }
}
// Определяем метод доступа get_Jeff
[IndexerName("Jeff")]
public String this[Boolean b] {
get { return null; }
}
}
Как видите, C# рассматривает индексаторы как механизм перегрузки операто-
ра
[]
, и этот оператор не позволяет различать свойства с
одинаковыми наборами
параметров и разными именами методов доступа.
Кстати, в качестве примера типа с измененным именем индексатора можно при-
вести тип
System.String
, в котором индексатор
String
именуется
Chars
, а не
Item
.
Это свойство позволяет получать отдельные символы из строки. Было решено, что
для языков программирования, не использующих синтаксис с оператором
[]
для
вызова
этого свойства, имя
Chars
будет более информативно.
Обнаружив попытку чтения или записи индексатора, компилятор C# генерирует
вызов соответствующего метода доступа. Некоторые языки программирования
могут не поддерживать свойства с параметрами. Чтобы получить доступ к свойству
с параметрами из программы на таком языке, нужно
явно вызвать желаемый метод
доступа. CLR не различает свойства с параметрами и без параметров, поэтому для
поиска связи между свойством с параметрами и его методами доступа используется
все тот же класс
System.Reflection.PropertyInfo
.
Do'stlaringiz bilan baham: