C# constructors
Asked Answered
D

9

12

Could someone advice me on what approach to take when writing C# constructors?

In other languages, like C++, everything is fine - you usually don't make the internal fields visible and provide getters / setters for them.

This means, you could provide your class with constructors, which initialize all / some of your local members and be happy.


C#, however, has properties, which allows us to write something like:

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

This allows chaining for the object construction and, as I assume, can remove a lot of constructors, which would be required if we didn't have properties.

Combining this with default values for properties, as I assume, we can completely get rid of non-specialized constructors, which actually do some work.

Now - is it okay to remove redundant constructors and allow object constructing via field initializing?

What are the drawbacks of this approach? Could someone give general recommendations about combining the usage of fields and constructors, some rules of thumb, probably?

Thank you.

Deficit answered 30/3, 2011 at 12:46 Comment(3)
yoda.arachsys.com/csharp/constructors.htmlZingg
those aren't fields, they are properties.Fionafionna
Other languages (esp. C++) have fields too. And in your examples Field1 is a property.Rosalinarosalind
S
16

My own rule of thumb is simple: If something is required to completely construct the object, it should be a ctor parameter.

A good example is one of the Stream helper objects like StreamReader or BinaryReader. They cannot function without an associated Stream object, so that must be specified in the constructor.

Somnus answered 30/3, 2011 at 12:49 Comment(0)
M
6

In my opinion, there is nothing wrong with having what you term as redundant constructors. If it makes enough sense for you to want to define a constructor, it is probably because there's a genuine need to do it that way.

Marketing answered 30/3, 2011 at 12:48 Comment(0)
C
4

Constructors can be used to force the consumer to supply values to the class.

My rule of thumb is that Fields are for optional data, while constructors can be used to force required data.

The question is something of a false dichotomy though. C++ behaves the same way as C# - "Fields" (which are actually properties - fields are class-level variables) are generally used as getters/setters for setting internal values, and the new syntax which allows you to set fields is just a shorthand for

Class x = new Class();
x.Field1 = new Field1();
x.Field2 = new Field2();
Claudie answered 30/3, 2011 at 12:49 Comment(0)
Z
2

Best practice is to create an object in a usable state; try to limit reliance on property setters.

It reduces the chances that you create an object which is incomplete and leads to less fragile code.

Zingg answered 30/3, 2011 at 12:49 Comment(0)
A
2

The code you posted is using what are called Object Initializers, which are really just syntactic sugar that were introduced fairly recently. Using object initializers are just a shorthand way of calling a constructor and setting properties. You should continue to use constructors in C# the same way that you have used them in other languages--the general rule is that if a class requires an object or value for it to be initialized properly, that parameter should be passed through the constructor. If the value isn't required, it is reasonable to make it a settable property.

Generally speaking, I avoid using setters at all when possible (there are many, many cases when it's not possible).

Annelieseannelise answered 30/3, 2011 at 12:50 Comment(0)
H
1

The approach of public parameterless construction followed by property initialization is popular (required?) for use in XAML, a lot of WPF toys do this.

The only problem you face is a partially initialized object, but then you can simply validate object state prior to attempting to use the fields.

Personally, I make critical values parameters in the constructor, I make copy constructors out of a copy of the object and a range of optional parameters, and I've yet to make something that needs consuming by XAML.

Horwitz answered 30/3, 2011 at 12:51 Comment(2)
I don't think the origianl question was about optional parameters, it was about object initialisors. However, optional parameters are another option here of course!Idiocrasy
It falls under the getting rid of specialized constructors point, but yes it wasn't directly mentioned. Makes my answer slightly different to the rest :-)Horwitz
S
1

The object initializer syntax is just a syntactic sugar. Even in C# 1 you could write

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

C# 3 basically shortens the syntax to:

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

The point od the counstructor is not to just set the fields, the constructor should logically construct the object, based on the parameters, so that when the constructor returns, what you get is an object that is ready to be used.

Selfsatisfaction answered 30/3, 2011 at 12:54 Comment(0)
I
0

Is it OK? Well, that depends...

In order to use object initialisers you will need to expose public setters to all your fields, you may not want this. If you are happy to expose them then I'd say go ahead and remove constructors. However just because you can do someting does not mean you should. I would say removing the constructors should be something you do if you find all your fields are publicly settable, do not make the fields settable just to allow you to remove the constructor.

Idiocrasy answered 30/3, 2011 at 12:51 Comment(0)
F
0

I suspect you are referring to domain objects here, but in the case of services, injecting the dependencies of the service in through a constructor makes the service more self documenting, as opposed to "newing up" your dependencies. Additionally this sets you up to use dependency injection containers more easily.

Flatfooted answered 30/3, 2011 at 12:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.