What is the difference between a class having private constructor and a sealed class having private constructor?

StackOverflow https://stackoverflow.com/questions/16639518

Question

Is there any difference between A and B?

Class A has private constructor:

class A
{
    private A()
    { }
}

Class B is sealed and has a private constructor:

sealed class B
{
    private B()
    { }
}
Was it helpful?

Solution

Yes A can be inherited by a nested class, while B cannot be inherited at all. This is perfectly legal:

public class A {
  private A() { }

  public class Derived : A { }
}

Note that any code could create a new A.Derived() or inherit from A.Derived (its constructor is public), but no other classes outside the source text of A can inherit directly from A.

A typical use for something like this is a class with enum-like values but which can have custom behavior:

public abstract class A {
  private A() { }

  public abstract void DoSomething();

  private class OneImpl : A { 
    public override void DoSomething() { Console.WriteLine("One"); }
  }

  private class TwoImpl : A { 
    public override void DoSomething() { Console.WriteLine("Two"); }
  }

  public static readonly A One = new OneImpl();
  public static readonly A Two = new TwoImpl();
}

OTHER TIPS

There is one tiny difference you can get, to do with Code Analysis.

Consider this code:

public class Base
{
    public virtual void Function()
    {
    }
}

public class Derived: Base
{
    public static  Derived Create()
    {
        return new Derived();
    }

    private Derived()
    {
        // Code analysis warning: CS2214 "Do not call overridable methods in constructors".
        Function(); 
    }
}

There is a Code Analysis warning for the Derived constructor, because we are accessing a virtual method from it, which is A Bad Thing.

However, if you make Derived sealed, the Code Analysis warning goes away.

So there's a tiny and contrived difference for you. ;)

Based on the second article if this is the only constructor you will not be able to create an instance of Class A or Class B. Because Class A has a private constructor you cannot derive from it due to its protection level, nor can you derive from B with sealed.

Inheritance (C# Programming Guide)

Derived Class Access to Base Class Members A derived class has access to the public, protected, internal, and protected internal members of a base class. Even though a derived class inherits the private members of a base class, it cannot access those members. However, all those private members are still present in the derived class and can do the same work they would do in the base class itself. For example, suppose that a protected base class method accesses a private field. That field has to be present in the derived class for the inherited base class method to work correctly.

Private Constructors (C# Programming Guide)

A private constructor is a special instance constructor. It is commonly used in classes that contain static members only. If a class has one or more private constructors and no public constructors, then other classes (except nested classes) are not allowed to create instances of this class.

A sealed class can be instantiated but a class with a private constructor can not. They both don't allow inheritance, but that's not the objective of a private constructor.

The reason you use a private constructor is to stop instantiation. This is often used in static factory methods, where you must call MyClass::Create(...) to create an instance.

This has nothing to do with sealing, which stops inheritance. If you use a private constructor to stop inheritance, then you're using the wrong approach. There are ways to get around a private constructor for inheritance.

If a class is sealed, it will not be possible to define a class which derives from it. A class with a private constructor may be instantiated by factory methods within the class, nor inherited by nested classes (which, depending upon their access level and constructors, may be inheritable by outside code). Additionally, arbitrary outside code may declare classes which derive from it and satisfy a new() constraint. If the derived class can't call a base constructor, its own constructors would have no alternative but to throw an exception, crash, or hang, but such behavior would not be detectable until an attempt was made to actually construct an instance; the code would compile fine.

public class Test
{


    private Test()
    {
        Debug.WriteLine("private constructor has been called in class Test");
    }

    public virtual string Run()
    {
        return "Test.Run";
    }

    public static Test GetTestRequest()
    {
        return new Test(); 
    }

    public static DerivedTest GetDerivedTestRequest()
    {
        return new DerivedTest();
    }

    public class DerivedTest:Test
    {
        public DerivedTest()
        {
            Debug.WriteLine("public constructor has been called in derived class DerivedTest.");
        }

        public override string Run()
        {
            return "DerivedTest.Run";
        }
    }
}

Debug.WriteLine(Test.GetTestRequest().Run()); Debug.WriteLine(Test.GetDerivedTestRequest().Run());

============================================================ Output:

private constructor has been called in class Test Test.Run

private constructor has been called in class Test public constructor has been called in derived class DerivedTest. DerivedTest.Run

So, a nested class can be derived from an outer base class having the only private constructor.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top