Search code examples
c#.netabstract-classdesign-guidelines

Abstract Class Design: Why not define public constructores?


Look here (Abstract Class Design): http://msdn.microsoft.com/en-us/library/ms229047.aspx

It says:

(1) Do not define public or protected internal (Protected Friend in Visual Basic) constructors in abstract types.

In C#, we are not able to instantiate an abstract class. So, does it still matter to define public constructors for abstract classes in C# ? Or not writing public constructors for abstract classes because of semantic meaning?

It also says:

(2) Do define a protected or an internal constructor in abstract classes.

Define internal constructors ?? In (1), it tells us that not defining internal protected constructors is because that "Constructors with public or protected internal visibility are for types that can be instantiated". Doesn't defining internal constructors for abstract classes break the rules in (1) ?

Thanks in advance. :)


Solution

  • Let's look at each of the cases.

    Recommended:

    • protected - The most obvious case - all subclasses can call the constructor, irrespective of which assembly they reside in (as long as the the abstract base-class itself is visible to them).

    • internal - Useful when you want the abstract type to be publicly visible, but not publicly inheritable. In this case, you would want to make all of the non-private constructors internal. Only subclasses within the same assembly as the abstract base-class would be able to call the constructors - effectively, only they would be able to inherit. Another use-case would be if you wanted a 'special' constructor that should only be visible to same-assembly subclasses.

    • private - Used mainly for 'dirty-work' constructors that are targeted by other constructors of the abstract class when it uses constructor-chaining. The only other use, when all the constructors are private, is to only allow subclassing by nested classes, which do have access to private members of the containing-type.


    Not recommended:

    • public - Not useful, behaves identically to protected. Only subclasses can call the constructor anyway, since the base-class is abstract.

    • protected internal - This too is no different from protected. The protected internal accessibility level means protected OR internal, not protected AND internal. However, the internal modifier here serves no purpose - it doesn't prevent subclasses residing outside the assembly from calling the constructor (assuming the abstract base-class is public) since they can rely on protected access, nor does it allow same-assembly types that are not subclasses from calling it (the type is abstract).

    The key point here is that every non-private constructor in an abstract class is already at best protected. The vanilla internal-modifier strengthens restrictions on who can call the constructor. public and protected internal don't accomplish anything because they appear to weaken restrictions, but don't really succeed in doing so.