C # private constructor

I read "Starting Visual C # 2012". I came across a question about the next part. Does anyone help me? see comments!

using System; using System.Collections.Generic; using System.Text; namespace Ch10Ex01 { class MyClass { public readonly string Name; private int intVal; public int Val { get { return intVal; } set { if (0 <= value && value <= 10) intVal = value; else throw (new ArgumentOutOfRangeException("Val", value, "Val must be assigned a value between 0 and 10.")); } } public override string ToString() { return "Name: " + Name + "\nVal: " + Val; } private MyClass() : this("Default Name") { } public MyClass(string newName) { Name = newName; intVal = 0; } } } 

Explanation in the book: note that I used this ("Default Name") to ensure that the name gets a value if this constructor is ever called, which is possible if this class is used to get a new class. This is necessary since not assigning a value to the Name field can be a source of errors later.

What puzzled me: how can it be used in a derived class as "private"? What does this mean ("Default Name")? ** How does an object get a "Default Name" as its name?

+4
source share
3 answers

What puzzled me: how can it be used in a derived class as "private"? What does this mean ("Default Name")? ** How does an object get a "Default Name" as its name?

You are right to be puzzled!

This sample code does not call the default constructor at all - and since it is private, nothing else can call it without using reflection (not even a derived class, it must be at least protected for the derived class to be called - or the derived class must be nested base class).

In the sample code, the object does not receive the "Default Name" value as its value.

So this is a typo or mistake in the book.

The correct solution for describing a book:

  • Omit the default constructor in general.
  • Initialize Name in the field. This ensures that it cannot be initialized, no matter what other constructors are written in this or any derived class.

Same:

 class MyClass { public readonly string Name = "Default Name"; private int intVal; public int Val { get { return intVal; } set { if (0 <= value && value <= 10) intVal = value; else throw (new ArgumentOutOfRangeException("Val", value, "Val must be assigned a value between 0 and 10.")); } } public override string ToString() { return "Name: " + Name + "\nVal: " + Val; } public MyClass(string newName) { Name = newName; intVal = 0; } } 

Note that it is often useful to declare a private default constructor that is called by other constructors, but the declaration class should really use it.

Also note that if you declare a non-default constructor in the base class and do not declare the default constructor at all, any derived class must call one of the existing base class constructors.

For example, if the class definition above is specified, then both of the following class declarations will cause a compilation error MyClass' does not contain a constructor that takes 0 arguments :

 class MyDerivedClass1: MyClass { public MyDerivedClass1() // Compile error { } } class MyDerivedClass2: MyClass { // No constructor declared at all. Also a compile error. } 

To fix the error, MyDerivedClass must call the existing constructor:

 class MyDerivedClass: MyClass { public MyDerivedClass(): base("My new name") { } } 

So what is a private constructor

A pretty typical use is to put common initialization code in the default constructor. Sometimes, however, you do not want the caller to be able to create a type by default β€” in this case, you can make the default constructor private.

That way, you can still use the default constructor for normal initialization, but you forbid using code outside the class, for example:

 class Test { public readonly int IntValue; public readonly string StringValue; private Test() { // Do common initialisation. } public Test(int intValue): this() { IntValue = intValue; } public Test(string stringValue): this() { StringValue = stringValue; } } 

Often you can use the private init() method to perform general initialization, but if you initialize the readonly field, you must use the constructor to do this. In this case, instead of the init() method, a private constructor should be used.

Another use of a private default constructor is to prevent any type instance at all (you simply declare your own default constructor and no other constructors at all).

In .Net 1.x, this was the only way to do this, but in subsequent versions of .Net, static classes were introduced that in most cases removed the need to use a private constructor for this type.

You can also declare a private constructor to force the static factory method to instantiate the type.


Just for completeness, here's a far-fetched example demonstrating how a private constructor can be called from a nested derived class:

 class OuterClass { public readonly string Value; private OuterClass(): this("Default Value") { } public OuterClass(string value) { Value = value; } public OuterClass GetInnerClass() { return new InnerClass(); } private class InnerClass: OuterClass { } } 

With this class definition, the following code will print "Default":

 OuterClass test = new OuterClass("Test"); Console.WriteLine(test.GetInnerClass().Value); 

Personally, I never had to write a nested class that derives from its containing class, but this is possible if you need to do this for some reason.

+7
source

Since this class has a private constructor, there is ONLY the way that the constructor can be called inside this particular class. Even a derived class cannot name it (if it was protected , then it could). As the code example shows, this is not practical.

The reason this is the default constructor calling the other is just the way to have a hard-coded default value without knowing / not worrying about what it is. This is similar to the default options for functions in .net 4.0.

It would be much wiser for me to make both constructors public, because I don’t see any code that uses the default constructor (if you showed us all the code).


There are some legitimate reasons for using private constructors, in particular with static functions or subclasses. Take for example the following:

 public class OuterClass { private OuterClass() { } public static OuterClass GetOuter() { return new OuterClass(); } } 

This way you can only create a new instance of the class from a static method.

0
source

A private constructor means that the user cannot directly instantiate the class. Instead, you can create objects using something like a Named Hierarchical Constructor, where you have static class functions that can create and return instances of a class. You can use a private constructor to control the instant object of an object commonly used in a singleton template.

You should read the singleton pattern to understand the purpose of a private constructor.

0
source

Source: https://habr.com/ru/post/1490156/


All Articles