Put the constructor of the class as 'private'?

18

When I put a constructor of a class in C # as private , I get the following error:

I would like to know the technical explanation for the reason for this error and if there is any use case of constructor (or one of the constructors) of a class as private .

    
asked by anonymous 26.02.2015 / 20:36

7 answers

5

We have several good answers here but since I mumbled something in each of them, I think it's fair that I expose my own.

As already mentioned, the reason for the error is that you are trying to use a class member (the constructor) that is not accessible outside of it because it is private.

And yes, there are cases of use or utility in declaring a constructor as private:

  

Declare a private constructor when you want this constructor to be accessible only to the class itself and its nested classes.

Sometimes only the class itself knows its constraints to be instantiated, so it is at these times that you declare the constructor as private . These restrictions can be:

  • The class wants to restrict only a single instance of it throughout the application's entire design life cycle.

  • The class wants to control its instances - for example by making a pool of instances of itself, then it creates its own instances (pattern design factory) and decides when to deliver a new instance or when delivering an existing instance.

  • The class requires that external consumers pass certain parameters to the constructor but want to be able to instantiate them without passing any parameters or passing parameters that do not matter publicly. In this case it would have public parametrized constructors and a non-parameterized private constructor or that would accept specific parameters that only need to be known internally.

These are the uses that occur to me at the moment but there may be more.

In addition to public and private , a constructor can also be protected , which allows it to be used exclusively by the class constructor daughters, and internal , which makes it accessible only to classes in the assembly .

Internal is useful for example to use the design pattern factory or instance pool, making another class in the same context responsible for these constraints instead of put all this knowledge within the class itself whose instantiation is controlled.

As for creating a private constructor for static classes, it is not very useful because in this case it is enough to declare the class itself as static ( static class).

    
27.02.2015 / 15:56
13

A private constructor is useful in cases where you want to prevent the class from being instantiated or want to allow it to be instantiated only within itself. This is useful for static classes or for implementing the Singleton and Factory .

An example can be found in this answer . Other examples are obviously in the other answers here.

Singleton ( removed from Wikipedia ):

using System;

public class MyClass {
   private static MyClass instance;
   private MyClass() {}
   public static MyClass Instance {
      get {
         if (instance == null) {
            instance = new MyClass();
         }
         return instance;
      }
   }
}
    
26.02.2015 / 21:21
9

The technical explanation is simple: the constructor can not be accessed from outside the class. So the error.

Private constructors are important when you want to enforce parameters for exposed (public) constructors. For example, constructors without parameters could be declared private so that their use is avoided. There is a caveat here: the parameterless constructor needs to do something, otherwise its statement does not make sense.

For example:

public class MinhaClasse 
{
    protected int MeuInteiroQuePrecisaSerPreenchido { get; set; }
    protected int OutraProperty { get; set; }

    // inacessível, portanto não pode ser usado fora da classe.
    private MinhaClasse() 
    { 
        OutraProperty = 5;
    } 

    // Aqui eu chamo o construtor sem parâmetros. 
    public MinhaClasse(int _meuInteiro) : this()
    {
        MeuInteiroQuePrecisaSerPreenchido = _meuInteiro;
    }
}

By default, the parameterless constructor of a class is public .

Still, suppose you want to define miscellaneous constructors (for checking data for arguments, for example). You can build constructors with varying levels of protection:

public class MinhaClasse2
{
    protected int MeuInteiro { get; set; }
    protected int OutraProperty { get; set; }
    protected String MinhaStringComValidacao { get; set; }

    // inacessível, portanto não pode ser usado fora da classe.
    private MinhaClasse() 
    { 
        OutraProperty = 5;
    } 

    private MinhaClasse(String _minhaString) : this()
    {
        if (_minhaString != "Valor que não pode") 
        {
            MinhaStringComValidacao = _minhaString;
        }
    }

    public MinhaClasse(int _meuInteiro, String _minhaString) : this(_minhaString)
    {
        MeuInteiro = _meuInteiro;
    }
}

Silly example, but only to demonstrate how it can be done.

    
26.02.2015 / 20:44
6

According to the MSDN documentation:

  

A private constructor is a special instance constructor. He is   generally used in classes that contain only static members. If   a class has one or more private constructors and none   other classes (except nested classes) can not   create instances of this class.

     

For example:

class NLog
{
    // Construtor privado:
    private NLog() { }

    public static double e = Math.E;  //2.71828...
}
  

The declaration of the empty constructor prevents the automatic generation of a   constructor. Note that if you do not specify a   access to the constructor will still be private by default. However, the   modifier private is usually used explicitly to make it clear   that the class can not be instantiated.

     

Builders   are used to prevent the creation of   class when there are no instance fields or methods, such as in the Math class,   or when a method is called to obtain an instance of a   class. If all methods of the class are static, consider making the entire class static.

Example:

public class Counter
{
    private Counter() { }
    public static int currentCount;
    public static int IncrementCount()
    {
        return ++currentCount;
    }
}

class TestCounter
{
    static void Main()
    {
        // A instrução abaixo irá gerar um erro porque o construtor é inacessível
        // Counter aCounter = new Counter();   // Erro

        Counter.currentCount = 100;
        Counter.IncrementCount();
        Console.WriteLine("New count: {0}", Counter.currentCount);

        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
// Output: New count: 101
    
26.02.2015 / 20:51
4

Here is a concrete case, implemented by the ASP.NET Web Api team itself on GitHub: link

I myself have applied the same here template.

Briefly, the two links above show a variation of the "Parameter Object" pattern. Public constructors of the class receive either their dependencies directly, or another object containing their dependencies.

Both public constructors wrap arguments in an instance of IDependencyProvider , which is passed to a private constructor that extracts dependencies and treats them uniformly. This builder is considered an implementation detail, the clients do not need to know about it, and therefore it is private.

public class MyClass
{
    private readonly string _dependency1;
    private readonly string _dependency2;

    public MyClass(string dependency1, int dependency2)
        : this(new DirectDependencyProvider(dependency1, dependency2))
    {
    }

    public MyClass(Container container)
        : this(new ContainerDependencyProvider(container))
    {
    }

    //constructor privado
    private MyClass(IDependencyProvider provider)
    {
        _dependency1 = provider.Dependency1;
        _dependency2 = provider.Dependency2;

        //etc, fazer alguma coisa com as duas dependencias
    }

    private interface IDependencyProvider
    {
        string Dependency1 { get; }
        int Dependency2 { get; }
    }

    private class DirectDependencyProvider : IDependencyProvider
    {
        private readonly string _dependency1;
        private readonly int _dependency2;

        public DirectDependencyProvider(string dependency1, int dependency2)
        {
            _dependency1 = dependency1;
            _dependency2 = dependency2;
        }

        public string Dependency1
        {
            get { return _dependency1; }
        }

        public int Dependency2
        {
            get { return _dependency2; }
        }
    }

    private class ContainerDependencyProvider : IDependencyProvider
    {
        private readonly Container _container;

        public ContainerDependencyProvider(Container container)
        {
            if(container == null)
                throw new ArgumentNullException("container");
            _container = container;
        }

        public string Dependency1
        {
            get { return _container.StringStuff; }
        }

        public int Dependency2
        {
            get { return _container.IntStuff; }
        }
    }
}

Note that the IDependencyProvider interface and its implementations are private types.

The alternative would be to use a private initialization method, but we would have to sacrifice the fields readonly and the guarantee of its immutability. This is a sacrifice that can be avoided.

public class MyClass
{
    private string _dependency1;
    private string _dependency2;

    public MyClass(string dependency1, int dependency2)
    {
        Initialize(dependency1, dependency2);
    }

    public MyClass(Container container)
    {
        if(container == null)
            throw new ArgumentNullException("container");

        Initialize(container.StringStuff, container.IntStuff);
    }

    private void Initialize(string dependency1, int dependency2)
    {
        _dependency1 = dependency1;
        _dependency2 = dependency2;
    }
}
    
27.02.2015 / 16:27
3

Another use case for a private constructor would be to implement the Singleton design pattern. By this standard, a class must have only one instance. To ensure this, the Singleton constructor is private. More information: link . Just remembering that Singleton is useful in only a few situations. It has a number of disadvantages (for example, it makes testing difficult), so it should be used with care.

    
26.02.2015 / 21:08
0

I believe that most uses are when we want to maintain a DDD and the framework forces us to have default constructor, example is the Entity Framework that forces all persistent entities to have constructors without parameter, but does not care about visibility. As you following the DDD and do not want "anemic" models you do not want class users to be able to use these builders and use that feature to hide them.

I agree that they also serve to protect classes with purely static methods, but there you have the ability to declare the static class, design issue.

@ Caffé: All classes have constructors, including static ones. Of course, these builders have more restrictions.

Perceive (linqpad):

void Main()
{
    Console.WriteLine(Xpto.msg);
}

static class Xpto
{
    public static string msg;

    static Xpto()
    {
        msg = "Blau";
    }
}
    
26.02.2015 / 23:38