Я знаю, я знаю ... Эрик Липперт обычно отвечает на этот вопрос примерно так: « Потому что это не стоило затрат на его разработку, внедрение, тестирование и документирование ».
Но все же мне хотелось бы получить более подробное объяснение ... Я читал это сообщение в блоге о новых функциях C # 4 , и в разделе о COM-взаимодействии мое внимание привлекла следующая часть:
Кстати, в этом коде используется еще одна новая функция: индексированные свойства (обратите внимание на квадратные скобки после Range). Но эта функция доступна только для COM-взаимодействия; вы не можете создавать свои собственные индексированные свойства в C # 4.0 .
Хорошо, но почему ? Я уже знал и сожалел о невозможности создания индексированных свойств в C #, но это предложение заставило меня снова задуматься об этом. Я вижу несколько веских причин для его реализации:
- CLR поддерживает его (например,
PropertyInfo.GetValue
имеетindex
параметр), поэтому жаль, что мы не можем воспользоваться этим в C # - он поддерживается для COM-взаимодействия, как показано в статье (с использованием динамической отправки)
- реализовано на VB.NET
- уже можно создавать индексаторы, то есть применять индекс к самому объекту, поэтому, вероятно, не составит большого труда распространить идею на свойства, сохранив тот же синтаксис и просто заменив
this
имя свойства
Это позволило бы писать такие вещи:
public class Foo
{
private string[] _values = new string[3];
public string Values[int index]
{
get { return _values[index]; }
set { _values[index] = value; }
}
}
В настоящее время единственный известный мне обходной путь - это создать внутренний класс ( ValuesCollection
например), реализующий индексатор, и изменить Values
свойство так, чтобы оно возвращало экземпляр этого внутреннего класса.
Это очень легко сделать, но раздражает ... Так что, возможно, компилятор сделает это за нас! В качестве варианта можно было бы создать внутренний класс, реализующий индексатор, и предоставить его через общедоступный общий интерфейс:
// interface defined in the namespace System
public interface IIndexer<TIndex, TValue>
{
TValue this[TIndex index] { get; set; }
}
public class Foo
{
private string[] _values = new string[3];
private class <>c__DisplayClass1 : IIndexer<int, string>
{
private Foo _foo;
public <>c__DisplayClass1(Foo foo)
{
_foo = foo;
}
public string this[int index]
{
get { return _foo._values[index]; }
set { _foo._values[index] = value; }
}
}
private IIndexer<int, string> <>f__valuesIndexer;
public IIndexer<int, string> Values
{
get
{
if (<>f__valuesIndexer == null)
<>f__valuesIndexer = new <>c__DisplayClass1(this);
return <>f__valuesIndexer;
}
}
}
Но, конечно, в этом случае свойство действительно вернет a IIndexer<int, string>
и не будет на самом деле индексированным свойством ... Было бы лучше сгенерировать реальное индексированное свойство CLR.
Что вы думаете ? Хотели бы вы увидеть эту функцию на C #? Если нет, то почему?