Я возвращаюсь к вопросам «почему бы и нет», потому что, во-первых, ответы почти никогда не бывают удовлетворительными - вы уже получили ответ «функция не такая, как вы хотите, потому что в спецификации не сказано, что вы хотите, чтобы она говорила» , который, как мне кажется, не был особенно удовлетворительным ответом. Во-вторых, команде дизайнеров не нужно объяснять, почему мир не такой, каким вы хотите его видеть; функции не существуют бесплатно, а затем создаются вне языка; скорее, функции должны быть сначала обоснованы, а затем разработаны.
Так что давайте постараемся сделать ваш вопрос «почему бы и нет» более четким. Существующая особенность заключается в том, что «инициализатор массива может использоваться (а) справа от равенства при инициализации или (б) справа от конструкции объекта типа массива». Предлагаемая особенность: «инициализатор массива также может использоваться как выражение». Вопрос в том, «какую критику Эрик высказал бы по поводу предлагаемой функции?»
Первая критика, которую я хотел бы сделать, это то, что неясно, каков тип выражения. В инициализаторе переменной у вас есть тип переменной, а в выражении создания объекта - тип объекта; по обоим из них мы можем определить тип построенного массива. Без каких-либо намеков, какой тип мы должны вывести?
В C # 1.0, когда эта функция была добавлена, в языке было сделано в общей сложности нулевые выводы типа. Принцип проектирования в первые дни C # был «без сюрпризов», а компилятор не был «слишком умным». Если разработчик хочет, чтобы выражение было определенного типа, этот тип должен быть каким-то образом очевиден в выражении. Когда ты говоришь
new double[] { 1, 2, 3.4 }
довольно ясно, какой тип предназначен. по аналогии
new Animal[] { cat, dog, null }
Предлагаемая функция нарушает этот принцип. Выражение должно иметь тип, но отнюдь не ясно, какой тип аргумента находится в
M({cat, dog, null})
Более того: предположим, что у нас есть две перегрузки M, одна из которых принимает массив, Animalа другая - массив IPet. Какая перегрузка Mприменима? Одно из преобразований лучше другого? Типы элементов: Catи Dog; имеет ли смысл выводить тип, которого там даже нет? Это все вопросы, которые должны быть рассмотрены командой разработчиков, и это вопросы, на которые нет очевидных ответов. Предлагаемая особенность очень быстро приводит нас в глубокие воды.
Теперь C # 3.0 решает эту проблему, потому что в C # 3.0 добавлены многочисленные функции, в которых компилятор определяет типы от имени разработчика. Предыдущие принципы «без сюрпризов» и «простые правила» противоречили другим принципам проектирования, необходимым для работы LINQ. Следует ли добавить предлагаемую вами функцию в C # 3.0?
Это могло бы быть. Фактически добавленная в C # 3.0 функция была:
new[] { x, y, z }
определяет тип массива с помощью алгоритма: возьмите выражения для элементов, которые имеют типы, определите, какой из этих типов является уникальным и наиболее общим типом, в который могут быть преобразованы все другие выражения, и, если такой тип существует, выберите его. Иначе выдаст ошибку,
Эту функцию можно было бы упростить, сделав ее new[]необязательной. Этого не было сделано.
Теперь, если бы вы попросили меня во временных рамках C # 3.0 критиковать предлагаемую функцию, я бы указал, что (1) компилятор C # 3.0 уже находился в серьезной опасности смещения графика для всего выпуска, поэтому давайте не будем больше добавлять бремя проектирования, реализации и тестирования совершенно ненужной функции, которая экономит пользователю шесть нажатий клавиш, и (2) C # 3.0 также добавил инициализаторы коллекций:
new List<int>() { 10, 20, 30 }
почему {10, 20, 30}автоматически должен быть массив ? Почему не должно быть List<int>? Или любой из множества других типов? Почему уклон в сторону массивов? Помните, что если мы решили закрепить синтаксис для массивов, мы застряли с ним навсегда . Это может никогда не быть чем - то другим, поэтому предлагаемая функция не только не нужна, но и предотвращает возможные будущие функции, которые кажутся правдоподобными.
Подводя итог: предлагаемая функция прямо нарушает некоторые принципы проектирования C # 1.0. Он не добавляет в C # 3.0 ничего, кроме ненужной нагрузки. Во всех версиях языка, начиная с C # 3.0, предлагаемая функция не имеет веских аргументов в пользу того, чтобы рекомендовать тратить на нее время, усилия и деньги вместо многих других более достойных функций.
Следовательно, такой особенности нет.