Dotnet Abstract Class Design Guidelines

As we know that we can never make instance of an abstract classes and abstract classes are meant to provide a kind of contract that forces all the subclasses to carry on the same hierarchies or standards. As we can never instantiate abstract classes so defining constructor properly is very important for good programming semantics.

So while designing abstract class defining constructors with appropriate access modifier is important.

Here are some recommendations for defining constructor access modifier in C#

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.

public abstract class Abstract1
{
private int myInternal1;
private float myInternal2;
private double myInternalDbl;
protected Abstract1(int p)
:this(p*200000.00)//Dirty Job
{
myInternal1 = p;
}
internal Abstract1(float p)
{
myInternal2 = p;
}
private Abstract1(double p)
{
myInternalDbl = p;
}
//For must implement
protected abstract void DoYour();
protected virtual void DoneHere()
{ 
//Some implementation
}
}

Not recommended Access Modifiers for C# Abstract class constructors

public – Not useful, behaves identically to protected during sub classing.  Making constructors public of abstract class with confuse developers to make an instance while writing code and will give compiler error so it is better not to make them public.

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).

Always provide at least one concrete class that inherits from each abstract class in your Library

Giving one concrete class for every abstract class with your lib will be very helpful to developers who will use your lib as they can use the concrete classes you have given to understand you abstract class design in a better ways.

For example, the .NET Framework provides the abstract classes WebRequest and WebResponse to handle sending requests to, and receiving replies from a Uniform Resource Identifier. As one of several concrete implementations for these abstract classes, the Framework includes the HttpWebRequest and HttpWebResponse classes, which are HTTP-specific implementations of the abstract classes.