2009-04-11 3 views
133

Каковы различия между ними и когда вы используете «инициализатор объектов» над «конструктором» и наоборот? Я работаю с C#, если это имеет значение. Кроме того, является ли метод инициализатора объекта конкретным для C# или .NET?В чем разница между инициализатором объекта и конструктором?

ответ

189

Инициализаторы объектов было что-то добавлено к C# 3, для того, чтобы упростить строительство объектов, когда вы используете объект.

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

MyObject myObjectInstance = new MyObject(param1, param2); 

В этом случае конструктор MyObject будет работать со значениями param1 и param2. Они оба используются для создания нового MyObject в памяти. Созданный объект (который настроен с использованием этих параметров) возвращается и устанавливается в myObjectInstance.

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

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

Это приводит к объекту инициализаторами - Объект Initializer позволяет задать свойства или поля на вашем объекте после он был построен, но перед тем вы можете использовать его чем-то другим. Например:

MyObject myObjectInstance = new MyObject(param1, param2) 
{ 
    MyProperty = someUsefulValue 
}; 

Это будет вести себя примерно так же, как если бы вы это сделать:

MyObject myObjectInstance = new MyObject(param1, param2); 
myObjectInstance.MyProperty = someUsefulValue; 

Однако в многопоточный средах неделимость объекта инициализаторе может быть полезным, поскольку оно (см. this answer) - это либо нулевой, либо инициализированный, как и предполагалось.

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

+22

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

+0

@ Reed-Copsey очень хорошее объяснение, будут ли какие-либо улучшения производительности с инициализаторами объектов или это только для удобства чтения? – Mahender

+2

@Mahender На самом деле, при использовании инициализаторов объектов обычно возникают (очень, очень малые) потери. Конструкторы могут быть написаны, чтобы быть более эффективными. –

40

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

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

Вы бы использовали конструктор без помощи инициализатора объекта, если конструктор достаточно задал начальное состояние объекта. Однако инициализатор объекта должен использоваться вместе с конструктором. Синтаксис требует явного или неявного использования (VB.Net и C#) конструктора для создания исходного объекта. Вы должны использовать инициализатор объекта, когда конструктор не будет достаточно инициализировать объект для вашего использования, и несколько простых полей и/или наборов свойств будут.

+13

Эта заметка «после» важна, спасибо – user8032

4

Конструктор - это метод (возможно), принимающий параметры и возвращающий новый экземпляр класса. Он может содержать логику инициализации. Ниже вы можете увидеть пример конструктора.


public class Foo 
{ 
    private SomeClass s; 
    public Foo(string s) 
    { 
     s = new SomeClass(s); 
    } 
} 

Теперь рассмотрим следующий пример:


public class Foo 
{ 
    public SomeClass s { get; set; } 
    public Foo() {} 
} 

Вы можете достичь того же результата, как и в первом примере с помощью инициализатора объекта, при условии, что вы можете получить доступ к SomeClass, со следующим кодом:


new Foo() { s = new SomeClass(someString) } 

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

11

Если у вас есть свойства, которые ДОЛЖНЫ быть установлены на вашем объекте, чтобы он работал правильно, один способ заключается в том, чтобы выставлять только один конструктор, который требует этих обязательных свойств в качестве параметров.

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

Инициализаторы объектов на самом деле просто «удобство синтаксиса» для сокращения первоначальных заданий. Приятно, но не очень функционально.

Марк

+0

Другой способ гарантировать, что существенные свойства заданы для объекта во время построения, - это обеспечить статический («заводский») метод для класса, который возвращает построенный объект. Этот заводский метод создает объект через конструктор * private *. (Может быть полезно определение нескольких частных конструкторов.) – DavidRR

+0

... Кроме того, иногда полезно создать статический заводский * класс *, который несет ответственность за построение экземпляров одного или нескольких других классов. Например, см. [File.Create Method (String)] (https://docs.microsoft.com/en-us/dotnet/api/system.io.file.create?view=netframework-4.7.1#System_IO_File_Create_System_String_) (и его перегрузки), который создает объект FileStream. – DavidRR

17

Когда вы

Person p = new Person { Name = "a", Age = 23 }; 

это то, что объект инициализатора по существу делает:

Person tmp = new Person(); //creates temp object calling default constructor 
tmp.Name = "a"; 
tmp.Age = 23; 
p = tmp; 

Теперь это облегчает поведение как this. Важно знать, как работают инициализаторы объектов.

+0

может это просто человек p = new Person {Name = "a" }? –

+0

@ nick-s да, очень. Для этого предназначен инициализатор объекта. Вы инициализируете членов, которых хотите. – nawfal

+2

Я не знал, что конструкторский парантезис можно пропустить. Благодарю. –

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