C# – Polymorphism

Polymorphism

Polymorphism is multiple forms of something. It can be achieved with operator overloading, method overloading, polymorphism via inheritance or polymorphism via interfaces.

Polymorphism has the ability for classes to provide different implementations of methods that are called through the same name. It allows you to invoke methods of derived class through base class reference during runtime.

It can happen with method overloading or method overriding.

Overloading – compile time

It is an early binding where methods with same name perform different tasks with different parameters but the return type should be same.

Overriding – runtime

It is a late binding approach using inheritance and virtual functions. Change the behavior of the method for the derived class.


Overloading Example:

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
           
            Test a = new Test();
            string name = "Jacinta";
            a.Foo(name);
            a.Foo(22,56.6f);
            

        }       

    }
    
    public class Test
    {
        public void Foo(string name)
        {
            Console.WriteLine("Your name is:{0}", name);
        }
        
        public void Foo(int age, float mark)
        {
            Console.WriteLine("Your age is:{0} and mark is: {1}", age,mark);
        }
    }
    
}

Overriding Example:

Class A is the base class, Class B inherits Class A. The method declared in the base class A is not re-declared in Class B but Class B has full access of Foo() method.

Case 1:

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
           
            A a = new A();
            a.Foo();            
            B b = new B();
            b.Foo();          

        }      

    }
    
    public class A
    {
        public void Foo()
        {
          Console.WriteLine("A::Foo()");
        }
    }
    
    public class B : A {}  
    
}

Output:
A::Foo()
A::Foo()

Case 2:

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
           
            A a = new A();
            a.Foo();
            
            B b = new B();
            b.Foo();
            
            a = b;
            a.Foo();
        }       

    }
    
    public class A
    {
        public void Foo()
        {
          Console.WriteLine("A::Foo()");
        }
    }
    
    public class B : A 
    {
        public void Foo()
        {
          Console.WriteLine("B::Foo()");
        }
    } 
}

Output:
A::Foo()
B::Foo()
A::Foo()

Note: If you copy derived class to base class and you want all derived class methods to be executed then you will need to explicitly declare virtual and override keyword.

Case 3:

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
           
            A a = new A();
            a.Foo();
            
            B b = new B();
            b.Foo();
            
            a = b;
            a.Foo();
        }       

    }
    
    public class A
    {
        public virtual void Foo()
        {
          Console.WriteLine("A::Foo()");
        }
    }
    
    public class B : A 
    {
        public override void Foo()
        {
          Console.WriteLine("B::Foo()");
        }
    } 
}

Output:
A::Foo()
B::Foo()
B::Foo()

C# – Partial Types and Methods

Partial Types and Methods

Each participant must have the partial declaration. Participants cannot have conflicting members. A constructor with the same parameters, for instance, cannot be repeated.

Partial methods

A partial type may contain partial methods. These let an auto-generated partial type
provide customization hooks for manual authoring. A partial method consists of two parts: a definition and an implementation. Partial methods must be void and are implicitly private.

partial class PaymentForm // In auto-generated file
{
...
partial void ValidatePayment (decimal amount);
}
partial class PaymentForm // In hand-authored file
{
...
partial void ValidatePayment (decimal amount)
{
if (amount > 100)
...
}
}

C# – Finalizers

Finalizers

Finalizers are class-only methods that execute before the garbage collector reclaims
the memory for an unreferenced object.

Unmanaged code modifier: unsafe

C# – Constant

Constant

  • A constant is a static field whose value can never change.
  • A constant can be any of the built-in numeric types, bool, char, string, or an enum type.
  • A constant is declared with the const keyword and must be initialized with a value.
  • Constants can also be declared local to a method.
public class Test
{
public const string Message = "Hello World";
}

Non-local constants modifiers:

Access modifiers: public internal private protected
Inheritance modifier: new

C# – Indexers

Indexers

With indexers you can access elements in a class or struct that encapsulate a list or dictionary of values. Accessed via index argument.

Example: String class has an indexer.

string s = "hello";
Console.WriteLine (s[0]); // 'h'
Console.WriteLine (s[3]); // 'l'

Can be called on null-conditional

string s = null;
Console.WriteLine (s?[0]); // Writes nothing; no error.

Implementing an indexer

You need to define property called this.

class Sentence
{
string[] words = "The quick brown fox".Split();
public string this [int wordNum] // indexer
{
get { return words [wordNum]; }
set { words [wordNum] = value; }
}
}

Sentence s = new Sentence();
Console.WriteLine (s[3]); // fox
s[3] = "kangaroo";
Console.WriteLine (s[3]); // kangaroo

C# – Abstract

Abstract

Abstract Class

  • A class declared as abstract can never be instantiated. Instead, only its concrete subclasses can be instantiated.
  • Specifies method signatures but lacks implementation.
  • It is used as a template for derived classes(base class).
  • Abstract class can have abstract and virtual members.
  • The subclass must provide implementation unless declared abstract

Link to Example

Abstract Methods

  • Abstract members cannot be private.
  • Abstract methods are implicitly virtual.
using System;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
           
           new Stock { SharesOwned = 200, CurrentPrice = 123.45M }.NetValue.Dump();
        }       

    }
    
        public abstract class Asset
        {
            public abstract decimal NetValue { get; }
        }

        public class Stock : Asset
        {
            public long SharesOwned;
            public decimal CurrentPrice;
            
            //override virtual method
            public override decimal NetValue => CurrentPrice * SharesOwned;
           
        }
    
}

Abstract Properties

//Abstract Class with abstract properties
abstract class absClass
{
    protected int myNumber;
    public abstract int numbers
    {
        get;
        set;
    }
}

class absDerived:absClass
{
    //Implementing abstract properties
    public override int numbers
    {
        get
        {
            return myNumber;
        }
        set
        {
            myNumber = value;
        }
    }
}

Rules:

  • Abstract class cannot be sealed.
  • Abstract methods are only allowed in abstract classes.
  • Abstract methods cannot be private.
  • Access modifier of the abstract method should be same in both abstract class and its derived class.
  • Abstract member cannot be static.
  • Abstract method cannot have virtual modifier.

Read more about Interface vs Abstract in Interface article.

C# – Inheritance modifiers

Inheritance modifiers

Virtual

Has default implementation in the base class. Virtual method is overridden by sub classes in order to provide specialized implementation. Methods, properties, indexers, and events can all be declared virtual. Subclass override a virtual method by applying the override modifier. The signatures, return types, and accessibility of the virtual and overridden methods
must be identical. An overridden method can call its base class implementation via the base keyword. Calling virtual methods from a constructor is potentially dangerous.

The virtual modifier tells the compiler that when any class derived from class A is used, an override method should be called.

virtual members cannot be private and virtual method is overwritten with the keyword override.

Why need virtual methods?

Sometimes we are not aware of all the types of objects that will occur when executed. It is better to re-implement functionality depending on the more specific types.

Instance and static methods are faster to invoke than interface and virtual methods.

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
           
           House mansion = new House { Name="McMansion", Mortgage=250000 };
	       Console.WriteLine (mansion.Liability);      // 250000
        }       

    }
    
    public class Asset
{
	public string Name;
	public virtual decimal Liability => 0;		// Virtual
        // Liability => 0 is a shortcut for { get { return 0; } }.
}

public class House : Asset
{
	public decimal Mortgage;
	public override decimal Liability => Mortgage;   // Overridden
    
}

public class Stock : Asset
{
	public long SharesOwned;
	// We won't override Liability here, because the default implementation will do.
}
    
}

C# – Inheritance

Inheritance

It can inherit from another class to extend or customize the original class. It allows you to reuse the functionality from the base class. A class can inherit from single class but it can be inherited by many classes.

Inheritance not only promotes code reuse but also helps to organize code into hierarchical structures.

public class Contact
{ ... }
public class BusinessContact : Contact
{ ... }
public class ProfessionalContact : Contact
{ ... }
public class PersonalContact : Contact
{ ... }
//base class
public class Asset
{
	public string Name;
}
//inherits from base class
public class Stock : Asset
{
	public long SharesOwned;
}

Derived classes (subclass) are classes which inherits the base class.

Base class is also called super class or the class that gets inherit from.

It is possible to cast operators to test or convert a base type to derived type.

Note

Sometimes it is better to introduce new virtual methods on the base class and implement it in the derived type.

It is important not to overuse inheritance and where possible use abstract class.

Hiding Inherited Members

Sometimes you want to hide the member from base class and redefine the same member in subclass. The new modifier allows you to obscure the base class member and use the subclass. You will need to add the keyword new to redefine the member from the base class into subclass.

using System;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
           
           B b = new B();
            b.Counter.Dump();
        }       

    }
    
        public class A 
        {
            public int Counter = 1;
        }
    
        public class B : A 
        {
            public new int Counter = 2;
        }
    
}

Constructors and Inheritance

A subclass must declare its own constructor. The base class constructor are accessible to the derived class but never automatically inherited. A subclass needs to define its own constructor thus it can call the base class constructor with the base keyword. Base class constructors always execute first to ensure that base initialization occurs before specialized initialization.

static void Main()
{
	new Subclass (123);
}

public class Baseclass
{
	public int X;
	public Baseclass () { }
	public Baseclass (int x) { this.X = x; }
}

public class Subclass : Baseclass
{
	public Subclass (int x) : base (x) { }
}


Implicit calling of the parameterless base-class constructor

If the subclass constructor misses the base keyword then the base class parameterless constructor is applied. If there is no parameterless constructor than subclasses base keyword is important.

static void Main()
{
	new Subclass();
}

public class BaseClass
{
	public int X;
	public BaseClass() { X = 1; }
}

public class Subclass : BaseClass
{
	public Subclass() { Console.WriteLine (X); }  // 1
}

Constructor and field initialization order
Once the object is instantiated, the following order of initialization takes place:
1. From subclass to base class: fields initialization and argument base-class constructors evaluation.
2. From base class to subclass: constructor bodies execute.

 public class A 
        {
            //Executes 3rd
            int x = 1;
            public A (int x)
            {
                //Executes 4th
                ....
            }
        }
    
        public class B : A 
        {
            //Executes 1st
            int y = 1;
            //Executes 2nd
            public B (int x): base (x + 1)
            {
                //Executes 5th
                .....
            }
        }

Overloading and Resolution

When overloading is called the most specific type has precedence. The overload is determined during compile time rather than at run time.

// When calling an overload method, the method with the most specific 
// parameter type match has precedence, based on the *compile-time* variable type:

static void Main()
{
	Foo (new House());		// Calls Foo (House)
	
	Asset a = new House();
	Foo (a);				// Calls Foo (Asset)
}

static void Foo (Asset a) { "Foo Asset".Dump(); }
static void Foo (House h) { "Foo House".Dump(); }

public class Asset
{
	public string Name;
}

public class Stock : Asset   // inherits from Asset
{
	public long SharesOwned;
}

public class House : Asset   // inherits from Asset
{
	public decimal Mortgage;
}

Related Article

Polymorphism
Casting and Reference Conversions
Virtual
Abstract
Virtual vs Override
New vs Override
Sealed
Base Keyword