Friday, 19 June 2015

Abstract and Sealed Classes

Sealed class

A sealed class cannot be inherited from.  It is recommended for classes that won't be derived from, or only contain static methods / properties.  Typically only used if writing a library.

Abstract class

An abstract class is used to represent something (an abstraction) that should never be instantiated.  You must derive from an abstract class.  All abstract classes must be overridden.  An abstract class establishes a "contract" for all derived classes.


public abstract class Control
{
   protected int top;
   protected int left;
   public Control(int top, int left)
  {
       this.top = top;
        this.left = left;
}

public class Button : Control
{
     public string Contents;
     public class Button(int top, int left, string contents)
            : base(top, left)
     {
            Contents = contents;
     }
}

In your program you cannot do this
Control c = new Control();
because you cannot create an instance of a control as it is declared abstract.

However you can create an instance of a derived class - i.e. create the concrete class - and assign that to a variable of type Control.
Control button = new Button(2, 3, "New Button");


The benefit of this is that you can create a collection of Control objects and iterate over them because all variables are of the same type, control.   You can execute the abstract method in the base class, and each concrete class will execute that correctly because they override the abstract base method in their own way.  Polymorphism is at work again.

Polymorphism: Inheritence, Overriding and Overloading

When a class inherits/derives from a parent class it inherits all protected and public methods in the base class.

Hiding methods and Overriding


If I implement a method in the child class with the same signature as one in the base class it will hide the base class's implementation.   The compiler alerts me to this and suggests a fix of adding the new keyword.  That will work as expected in some but not all conditions.

It is perfectly legal to declare a new variable of the base class and populate it with a new child class:

Base newbie = new child();

This is because the child class has an "Is A" relationship with the base class.  A child is a base so the above works.  However if you invoke the method that has been hidden in the child class, what executes and is output is the implementation in the base class (because newbie is of type Base).  This isn't what was expected because newbie is really a child.   We want, instead of hiding the child's implementation to override the base implementation with the child implementation.

To override instead of hide a method, in the base class mark the method as virtual (which indicates we expect it to be overriden in a child class) and in the child class replace new with override in the signature of the method.

This allows the methods to implement polymorphism as the method behaves differently/correctly depending on the type of each object.
Overloading = virtual methods in a derived class.

Method Overloading

It's important to remember that the signature of a method is its name and parameter list (but not its return type).
You can overload methods - methods in a class can have the same name provided:
Different number of parameters
Different type of parameters

Overloading = same method name in one class.
You can both overload and override methods

You can also overload constructors - very handy and saves duplicating code




Monday, 1 June 2015

Default and Named Parameters

Default and Named Parameters were new features in C# 4.0

Default Parameters

Methods can take parameters that are optionally nullable like thus:-

public void SomeMethod(DateTime? time)

In C# 4.0 This can be called by this code
SomeMethod();

As the parameter is nullable it is now also optional.  Optional parameters can only be listed after all required parameters.  There are two syntaxes for doing this


  1. Optional Keyword
    Requires the addition of another using statement as well as the optional attribute

    using System.Runtime.InteropServices;

    public void SomeMethod([Optional] DateTIme? time)

    If the caller doesn't provide a value for an optional parameter then it will be assigned the type's default value (null for reference types, 0 for many numeric types).
  2. Specify a default value
    Doesn't require the using statement.  This also allows you to specify what the default value is

    public void SomeMethod(DateTime? time = null, int value = 3) 

    Note the compiler must be able to compute the value provided; It must be a compile time constant.   You couldn't use DateTime.Now() as a constant for example. 

Named Parameters

When calling a method and passing in parameters it can be unclear what the parameters are for, particularly if you pass null as one of the parameters.  You can name the parameters in the call (the name must match that given in the signature) with a colon and the value to pass to that parameter in the method call.

SomeMethod(time: DateTime.Now);
SomeMethod(value: 3);

In the second example above the time parameter is omitted and hence it gets the default value, null.
This is useful for the situation where parameters or values passed aren't very descriptive and make reading the code harder.