Я знаю, я знаю... Ответ Eric Lippert на этот вид вопроса обычно - что-то как, "потому что это не стоило стоимости разработки, реализации, тестирования и документирования его".
Но тем не менее, я хотел бы лучшее объяснение... Я читал это сообщение в блоге о новом C# 4 функции, и в разделе о COM Interop, следующая часть привлекла мое внимание:
Между прочим, этот код использует еще одну новую функцию: индексируемые свойства (более тщательно изучают те квадратные скобки после Диапазона.), Но эта функция доступна только для взаимодействующего с COM; Вы не можете создать свои собственные индексируемые свойства в C# 4.0.
Хорошо, но почему? Я уже знал и сожалел, что не было возможно создать индексируемые свойства в C#, но это предложение заставило меня думать снова об этом. Я вижу несколько серьезных оснований реализовать его:
PropertyInfo.GetValue
имеет index
параметр), поэтому жаль, что мы не можем использовать в своих интересах его в C#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
{
TValue this[TIndex index] { get; set; }
}
public class Foo
{
private string[] _values = new string[3];
private class <>c__DisplayClass1 : IIndexer
{
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 <>f__valuesIndexer;
public IIndexer Values
{
get
{
if (<>f__valuesIndexer == null)
<>f__valuesIndexer = new <>c__DisplayClass1(this);
return <>f__valuesIndexer;
}
}
}
Но конечно, в этом случае свойство на самом деле возвратило бы a IIndexer
, и действительно не было бы индексируемое свойство... Было бы лучше генерировать реальное индексируемое свойство CLR.
Что Вы думаете? Хотели бы Вы видеть эту функцию в C#? В противном случае, почему?
Вот как мы разработали C # 4.
Сначала мы составили список всех возможных функций, которые мы могли бы добавить в язык.
Затем мы сгруппировали функции как «это плохо, мы никогда не должны этого делать», «это круто, мы должны это сделать» и «это хорошо, но давайте не будем делать это в этот раз».
Затем мы посмотрели, сколько бюджета у нас было на проектирование, внедрение, тестирование, документирование, поставку и поддержку необходимых функций, и обнаружили, что мы на 100% превышаем бюджет.
Итак, мы переместили кучу вещей из ведра «надо иметь» в ведро «хорошо иметь».
Проиндексированные свойства никогда не находились в верхней части списка "обязательных". Они очень низкие в списке «хороших» и заигрывают со списком «плохих идей».
Каждая минута, которую мы тратим на разработку, внедрение, тестирование, документирование или поддержку хорошей функции X, - это минута, которую мы не можем потратить на отличные функции A, B, C, D, E, F и G. Мы должны безжалостно расставлять приоритеты, чтобы что мы делаем только самые лучшие функции. Индексированные свойства были бы хороши, но даже близко не достаточно хороши, чтобы их можно было реализовать.
Индексатор в C# является индексированным свойством. По умолчанию оно называется Item
(и вы можете обращаться к нему как к таковому, например, из VB), и вы можете изменить его с помощью IndexerNameAttribute, если хотите.
Я не уверен, почему именно так было задумано, но, похоже, это намеренное ограничение. Тем не менее, оно согласуется с Framework Design Guidelines, которые рекомендуют подход, когда неиндексированное свойство возвращает индексируемый объект для коллекций-членов. Т.е. "быть индексируемым" - это свойство типа; если он индексируется более чем одним способом, то его действительно следует разделить на несколько типов.
Поскольку вы уже можете делать это, и это заставляет вас думать в аспектах OO, добавление индексированных свойств просто добавит больше шума в язык. И просто еще один способ сделать еще одну вещь.
class Foo
{
public Values Values { ... }
}
class Values
{
public string this[int index] { ... }
}
foo.Values[0]
Я лично предпочел бы видеть только один способ сделать что-то, а не 10 способов. Но, конечно, это субъективное мнение.
Я бы сказал, что они не добавили его, потому что это не стоило затрат на его разработку, внедрение, тестирование и документирование.
Шутя в сторону, это, вероятно, потому, что обходные пути просты, и эта функция никогда не сокращает время по сравнению с выгодами. Я не удивлюсь, если в будущем это покажется изменением.
Вы также забыли упомянуть, что более простой способ решения проблемы - это просто создать обычный метод:
public void SetFoo(int index, Foo toSet) {...}
public Foo GetFoo(int index) {...}
Другой обходной путь указан в Простое создание свойств, поддерживающих индексацию в C # , что требует меньше работы.
РЕДАКТИРОВАТЬ : я должен также добавить, что в ответ на исходный вопрос, если мы сможем реализовать желаемый синтаксис с поддержкой библиотеки, то я думаю, что должны быть очень веские аргументы, чтобы добавить его непосредственно в язык, чтобы свести к минимуму языковой раздувание.