Прежде всего, давайте сделаем правильные условия.Это не коллекция инициализатор.Это инициализатор массива .Инициализатор коллекции всегда следует за конструктором для типа коллекции.Инициализатор массива допустим только в инициализаторе объявления локального или поля или в выражении создания массива.
Вы совершенно правы, заметив, что это странное правило.Позвольте мне точно охарактеризовать его странность:
Предположим, у вас есть метод M, который принимает массив целых чисел.Все это допустимо:
int[] x = new[] { 10, 20, 30 };
int[] y = new int[] { 10, 20, 30 };
int[] z = new int[3] { 10, 20, 30 };
M(new[] { 10, 20, 30 });
M(new int[] { 10, 20, 30 });
M(new int[3] { 10, 20, 30 });
Но
int[] q = {10, 20, 30}; // legal!
M( { 10, 20, 30 } ); // illegal!
Кажется, что либо «одиночный» инициализатор массива должен быть законным везде, чем «декорированный», либо нигде.Странно, что существует это псевдо-выражение, которое допустимо только в инициализаторе, а не где-либо еще, где выражение является допустимым.
Прежде чем и критиковать, и защищать этот выбор, я хочу сказать, что в первую очередь,это несоответствие является исторической случайностью.Там нет убедительно веских причин для этого.Если бы мы могли избавиться от этого, не нарушая код, мы бы.Но мы не можем.Если бы сегодня мы снова создавали C # с нуля, я думаю, что есть хорошие шансы, что «одиночный» инициализатор массива без «new» не будет правильным синтаксисом.
Итак, позвольте мне сначала привести несколько причин, по которым инициализаторы массива НЕ должны быть разрешены в качестве выражений и должны быть разрешены в инициализаторах локальных переменных.Затем я приведу несколько причин обратного.
Причины, по которым инициализаторы массива не должны быть разрешены в качестве выражений:
Инициализаторы массива нарушают свойство nice, которое {
всегда означает введение новогоблок кода.Синтаксический анализатор восстановления в среде IDE, который выполняет синтаксический анализ при вводе текста, любит использовать фигурные скобки как удобный способ определить, когда оператор является неполным;если вы видите:
if (x == M(
{
Q(
Тогда редактору кода будет довольно легко догадаться, что вы пропустили ))
до {
.редактор предположит, что Q(
является началом оператора, и он пропускает его конец.
Но если инициализаторы массива являются допустимыми выражениями, возможно, что то, чего не хватает, это )})){}
Q
.
Во-вторых, инициализаторы массивов в качестве выражений нарушают хороший принцип, согласно которому во всех выделениях кучи где-то есть «новые».
Причины, по которым инициализаторы массивов должны быть разрешены вполевые и локальные инициализаторы:
Помните, что инициализаторы массивов были добавлены в язык в версии 1.0 до неявно типизированных локальных, анонимных типов или вывода типов в массивах.Раньше у нас не было приятного синтаксиса "new [] {10, 20, 30}", поэтому без инициализаторов массива вы должны были бы сказать:
int[] x = new int[] { 10, 20, 30 };
, что кажется очень избыточным!Я могу понять, почему они хотели получить этот "новый int []" оттуда.
Когда вы говорите
int[] x = { 10, 20, 30 };
, это не является синтаксически неоднозначным;синтаксический анализатор знает, что это инициализатор массива, а не начало блока кода (в отличие от случая, который я упомянул выше). Он также не является неоднозначным по типу;ясно, что инициализатор - это массив целых чисел из контекста.
Так что этот аргумент оправдывает, почему в C # 1.0 инициализаторы массива были разрешены в локальных и полевых инициализаторах, но не в контекстах выражений.
Но это не тот мир, в котором мы находимся сегодня.Если бы мы проектировали это с нуля сегодня, у нас, вероятно, не было бы инициализаторов массива, у которых нет «нового».В настоящее время, конечно, мы понимаем, что лучшее решение:
var x = new[] { 10, 20, 30 };
, и это выражение допустимо в любом контексте.Вы можете явно ввести его либо на стороне «объявления», либо на стороне «инициализатора» =
, если считаете нужным, или вы можете позволить компилятору выводить типы с обеих сторон или с обоими.
Итак, подводя итог, да, вы правы в том, что несовместимо, чтобы инициализаторы массива могли быть только в локальных и полевых объявлениях, но не в контекстах выражений. Десять лет назад для этого была веская причина, но в современном мире с выводом типов больше нет веских причин для этого. На данный момент это просто историческая случайность.