Подтвердить что ты не робот

Конструкторы С#

Может ли кто-нибудь посоветовать мне, какой подход принять при написании конструкторов C#?

В других языках, таких как C++, все в порядке - вы обычно не делаете видимыми внутренние поля и предоставляете им getters/setters.

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


C#, однако, имеет properties, что позволяет нам написать что-то вроде:

Class x = new Class { Field1 = new Field1 ...., Field2 = new Field2 }

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

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

Теперь - можно ли удалить избыточные конструкторы и разрешить создание объекта с помощью инициализации поля?

Каковы недостатки такого подхода? Может ли кто-нибудь дать общие рекомендации о объединении использования полей и конструкторов, некоторые rules of thumb, возможно?

Спасибо.

4b9b3361

Ответ 1

Мое собственное правило очень просто: если что-то требуется для полной конструирования объекта, это должен быть параметр ctor.

Хорошим примером является один из вспомогательных объектов Stream, таких как StreamReader или BinaryReader. Они не могут функционировать без связанного объекта Stream, поэтому он должен быть указан в конструкторе.

Ответ 2

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

Ответ 3

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

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

Однако вопрос заключается в ложной дихотомии. С++ ведет себя так же, как С# - "Поля" (которые на самом деле являются свойствами - полями являются переменными уровня класса) обычно используются в качестве геттеров/сеттеров для установки внутренних значений, а синтаксис new, который позволяет вам устанавливать поля, - это просто сокращение для

Class x = new Class();
x.Field1 = new Field1();
x.Field2 = new Field2();

Ответ 4

Лучшей практикой является создание объекта в пригодном для использования состоянии; попытайтесь ограничить зависимость от установок свойств.

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

Ответ 5

Введенный вами код использует то, что называется Object Initializers, которые на самом деле являются просто синтаксическим сахаром, которые были введены совсем недавно. Использование инициализаторов объектов - это просто сокращенный способ вызова конструктора и установки свойств. Вы должны продолжать использовать конструкторы на С# так же, как вы использовали их на других языках - общее правило состоит в том, что если класс требует, чтобы объект или значение для его правильной инициализации, этот параметр должен передаваться через конструктор. Если значение не требуется, разумно сделать его настраиваемым.

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

Ответ 6

Подход публичной конструкции без параметров, за которым следует инициализация свойств, является популярным (требуется?) для использования в XAML, это делает много игрушек WPF.

Единственная проблема, с которой вы сталкиваетесь, - это частично инициализированный объект, но затем вы можете просто проверить состояние объекта перед попыткой использовать поля.

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

Ответ 7

Синтаксис инициализатора объекта - это просто синтаксический сахар. Даже в С# 1 вы можете написать

Class c = new Class();
c.Property1 = value1;
c.Property2 = value2;
c.Property3 = value3;
....

С# 3 в основном сокращает синтаксис до:

Class c = new Class 
{
   Property1 = value1, 
   Property2 = value2, 
   Property3 = value3
   ....
}

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

Ответ 8

Все в порядке? Ну, это зависит...

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

Ответ 9

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