C# сложность инициализатора объекта. лучшая практика

Я был слишком взволнован, когда в C# появился объектный инициализатор.

MyClass a = new MyClass();
a.Field1 = Value1;
a.Field2 = Value2;

можно переписать короче:

MyClass a = new MyClass { Field1 = Value1, Field2 = Value2 }

Код инициализатора объекта более очевиден, но когда количество свойств приближается к дюжине, а некоторые из назначений имеют дело со значениями, допускающими значение NULL, трудно отладить, где находится «ошибка нулевой ссылки». Studio показывает весь инициализатор объекта как точку ошибки.

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

Как вы используете объектный инициализатор для сложного присваивания или это плохая практика вообще использовать дюжину присваиваний?

Заранее спасибо!


person Andrew Florko    schedule 18.06.2010    source источник


Ответы (3)


Что ж, моя главная претензия к инициализаторам объектов заключается в том, что для начала им требуется изменяемый тип: там, где это возможно, я предпочитаю использовать неизменяемые типы. Сказав это, когда инициализатор объекта будет работать (например, для элементов управления пользовательского интерфейса), я склонен использовать их.

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

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

Очевидно, что модерация - это всегда хорошо - я не предлагаю доводить это до крайности... но если вы устанавливаете дюжину свойств, использование инициализатора объекта не будет для меня такой большой проблемой, как наличие дюжины свойств. установить для начала. Связаны ли какие-либо из этих десятков свойств? Должны ли они быть как-то инкапсулированы вместе? (В некоторых случаях это нормально — опять же, особенно с элементами управления пользовательского интерфейса, — но часто это не так.)

person Jon Skeet    schedule 18.06.2010
comment
Обычно у меня такой код при работе с бизнес-объектами. Свойства заполняются из пользовательского интерфейса или поступают из разных таблиц. - person Andrew Florko; 18.06.2010
comment
Я склонен не любить инициализаторы объектов в DAO, потому что вы обычно получаете поле от читателя, и часто что-то может пойти не так. Вы не получаете никакой безопасности компилятора. В этом случае вы не можете защитить себя с помощью модульного теста, потому что он становится интеграционным тестом. Сущности вне БД обычно имеют пару полей, связанных с ними. Однако, если назначения тривиальны, я буду использовать инициализатор объекта. - person uriDium; 14.05.2013

Если вы отлаживаете свое приложение, то в большинстве случаев вы должны иметь возможность использовать инструменты отладки VS, чтобы определить, какое назначение вызывает нулевую ссылку.

Однако, если вы разделите задание на несколько строк, я думаю, что VS укажет на правильную строку при возникновении исключения:

MyClass a = new MyClass {
                    Field1 = Value1,
                    Field2 = Value2 };

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

person ErikHeemskerk    schedule 18.06.2010
comment
Нет, нет :) Моя студия выделяет все строки инициализатора объекта, когда возникает ошибка, и я не знаю, какое свойство имеет проблему - person Andrew Florko; 18.06.2010
comment
Понимаю. Затем, я думаю, для целей отладки это своего рода бремя, если только вы не хотите навести курсор мыши на каждое выражение, которое вы назначаете полям, и посмотреть, какое из них является нулевым. - person ErikHeemskerk; 18.06.2010

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

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

Помните, что инициализаторы объектов были введены в язык в первую очередь для того, чтобы сделать синтаксис Linq допустимым. Это не означает, что его следует использовать более широко.

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

person Daniel Dyson    schedule 18.06.2010
comment
вы не должны возиться с хорошо протестированным и работающим кодом только для того, чтобы его было легче читать — использование инициализатора объекта — один из самых безопасных рефакторингов. Вы вообще не сторонник рефакторинга? - person Jon Skeet; 18.06.2010
comment
Да, Джон, я полностью согласен с тобой в этом вопросе. Рефакторинг там, где это имеет смысл. Можно ли повысить производительность и сделать код более безопасным и надежным. Конечно, изменение типов на неизменяемые, как вы упомянули в своем ответе, является лучшей практикой. Но простой рефакторинг для использования инициализаторов объектов часто не является хорошей тратой времени. - person Daniel Dyson; 18.06.2010
comment
Вы вполне могли бы использовать LINQ без инициализаторов объектов (даже анонимных типов, потому что я думаю, что вы имеете в виду это), хотя это было бы намного сложнее читать. - person ErikHeemskerk; 18.06.2010