2011-01-13 1 views
4

Чтобы использовать синтаксис инициализации, как это:Почему метод Add необходим для {} инициализации?

var contacts = new ContactList 
{ 
    { "Dan", "[email protected]" }, 
    { "Eric", "[email protected]" } 
}; 

... Я понимаю, что мой ContactList тип would need to define an Add method, которая принимает два параметра: string

public void Add(string name, string email); 

Что немного сбивает с толку мне о том, что синтаксис инициализатора { } представляется наиболее полезным при создании коллекций только для чтения или фиксированного размера. В конце концов, он предназначен для имитации синтаксиса инициализации для массива , правильно? (ОК, поэтому массивы не доступны только для чтения, но они - фиксированный размер). И, естественно, его можно использовать только тогда, когда содержимое коллекции известно (по крайней мере, количество элементов) во время компиляции.

Таким образом, было бы почти казаться, что основное требование для использования синтаксиса инициализатора коллекции (имеющего метод Add и, следовательно, изменяемую коллекцию) противоречит типичному случаю, в котором это было бы наиболее полезно.

Я уверен, что я не задумывался над этим вопросом, как команда разработчиков C#; просто кажется, что для этого синтаксиса могут быть разные правила, которые бы лучше соответствовали бы его типичным сценариям использования.

Как я отступаю от базы здесь? Желательно ли использовать синтаксис { } для инициализации коллекций фиксированного размера, которые не так распространены, как я думаю? Какие другие факторы могли повлиять на формулировку требований к этому синтаксису, о которых я просто не думаю?

ответ

2

Причина этого в том, что она была модифицирована. Я согласен с вами в том, что использование конструктора, берущего коллекцию, будет иметь гораздо больший смысл, но не все существующие классы коллекции реализовали это, и изменение должно (1) работать со всеми существующими коллекциями, (2) не изменять существующие классы в любом путь.

Это компромисс.

2

Основная причина: Syntactic Sugar.

Синтаксис инициализатора упрощает программирование записи на C#. На самом деле это не добавляет какой-либо выразительной способности к языку.

Если инициализатору не нужен метод Add(), тогда это будет совсем другая функция, чем сейчас. В принципе, это не так, как работает C#. Для создания общих коллекций нет литерала.

+2

Это добавляет выразительную силу к языку; он позволяет выразить инициализацию коллекции * в виде дерева выражений lambda *. –

+0

@ Эрик, вы все равно не можете сделать это в блоке выбора? Или инкапсулировать его в метод? – jjnguy

+0

Выберите не принимает блок, он принимает выражение. И как инкапсулировать его в методе помощи в случае дерева выражений? Как переводчик запросов знает, что метод инициализирует коллекцию и что семантика «инициализировать коллекцию» должна быть переведена в инструкции на уровне доступа к данным? –

2

Не ответ, строго говоря, но если вы хотите знать, какие вещи повлияли на дизайн инициализаторов коллекции, то вы, вероятно, найти этот интересный:

+0

Определенно помогает понять некоторые из особенностей, стоящих за функцией-благодарностью. –

1

Что должен использовать синтаксис инициализации, если не метод Add? Синтаксис инициализации «запускается» после запуска конструктора коллекции, и сбор полностью создается. Должно быть способ добавления элементов в коллекцию после ее создания.

Если вы хотите инициализировать коллекцию только для чтения, сделайте это в конструкторе (принимая T[] items аргумент или аналогичный)

3

Это потому, что оператор инициализации стенография для CLR. Когда он скомпилируется в байт-код, он вызывает метод Add, который вы определили.

Таким образом, вы можете сделать так, чтобы этот оператор инициализации не был действительно функцией «первого класса», потому что он не имеет аналога в IL. Но это касается довольно много того, что мы используем, например, «использование».

1

Насколько я понимаю, синтаксис инициализатора коллекции равен syntactic sugar без особых трюков. Он был разработан в рамках поддержки инициализацией коллекций внутри запросов Linq:

from a in somewhere 
select new { 
    Something = a.Something 
    Collection = new List<object>() { 
     a.Item1, 
     a.Item2, 
     ... 
    } 
} 

До этого не было никакого способа сделать это инлайн, и вы должны были бы сделать это после того случая, который был раздражающим.

+0

Это синтаксис для построения анонимных типов, а не инициализатор коллекции. – CodesInChaos

+0

Обратите внимание на объект списка внутри анонимного типа. –

1

Мне очень хотелось бы иметь синтаксис инициализатора для неизменяемых типов (обе коллекции и обычные типы). Я думаю, что это может быть реализовано с помощью специальной перегрузки конструктора с использованием синтаксиса, подобного params.

Например, что-то вроде этого:

MyClass(initializer KeyValuePair<K,V>[] initialValues) 

Но, к сожалению, C# команда не реализовать такую ​​вещь еще :(

Таким образом, мы должны использовать обходной путь, как

MyClass(new KeyValuePair<K,V>[]{...}) 

на данный момент

1

Инициализаторы коллекции: выражения, поэтому они могут использоваться там, где действительны только выражения, такие как инициализатор поля или запрос LINQ. Это делает их существование очень полезным.

Я также считаю, что тип инициализации в виде фигурных скобок { } пахнет скорее как коллекция фиксированного размера, но это всего лишь выбор синтаксиса.

10

Я уверен, что я не задумывался над этим вопросом, как команда разработчиков C#; просто кажется, что для этого синтаксиса могут быть разные правила, которые бы лучше соответствовали бы его типичным сценариям использования.

Ваш анализ очень хороший; ключевой проблемой являются последние три слова в приведенном выше утверждении. Каковы фактические типовые сценарии использования ?

Побочным дизайном цели мотивирована типичными сценарии использования для инициализаторов сбора была сделать инициализации из существующих типов коллекций возможна в синтаксисе выражения так, что инициализаторы коллекции могут быть встроен в постижениях запросов или преобразуется в деревья выражений.

Каждый другой сценарий имеет более низкий приоритет; функция существует вообще, потому что она помогает LINQ работать.

Команда компилятора C# 3 была «длинным полюсом» для этой версии Visual Studio/.NET. У нас было большинство дней работы по расписанию любой команды, что означало, что каждый день мы задерживали продукт будет отложено. Мы хотели отправить качественный продукт вовремя всем вам, ребята, и совершенным является враг хорошего. Да, эта функция немного неуклюжая и не делает абсолютно все, что вам может понадобиться, но было более важно получить ее прочной и проверенной для LINQ, чем заставить ее работать на кучу неизменных типов коллекций, которые в значительной степени не даже если есть.

Если бы эта функция была разработана на языке с первого дня, , в то время как типы фреймворков все еще развивались, я уверен, что все пошло бы иначе. Как мы уже обсуждали в другом месте на этом сайте, мне очень хотелось бы иметь массив значений фиксированного размера с записью в один раз. Было бы неплохо определить общий шаблон для создания кучи состояния для инициализации произвольной неизменяемой коллекции. Вы правы, что синтаксис инициализатора коллекции идеально подходит для такой вещи.

Такие функции, как в списке, для будущих будущих версий гипотетического языка, но не слишком высокого в списке. Другими словами, давайте сначала перейдем к async/await, прежде чем слишком сильно подумаем о синтаксических сахарах для неизменной инициализации коллекции.

+0

Спасибо, Эрик-определенно помогает поставить это в перспективе. Я думаю, что когда-то несколько человек упомянули LINQ, осознание начало устанавливать (для меня), что это был настоящий мотиватор для инициализаторов коллекции; то все начинало иметь смысл. –

+0

Кстати, я не думаю, что вы столкнулись с [этим (несвязанным) вопросом] (http://stackoverflow.com/questions/4642665/)? Я не хочу быть противным, поднимая его сюда; это просто дурно. И ваше имя было упомянуто в комментарии или два ... –

 Смежные вопросы

  • Нет связанных вопросов^_^