TypeA T1 = new TypeA();
TypeB T2 = new TypeB();
// Not Binding: Reference from Parent --> object from Parent
  • ุฅู†ูŠ ุฃุนู…ู„ Reference ูŠุดุงูˆุฑ ุนู„ู‰ Child ู„ู„ู€ class ุงู„ู„ูŠ ุจุนู…ู„ ู…ู†ู‡ Reference
  • ุจู…ุนู†ู‰ ุฅู†ูŠ ุฃู‚ุฏุฑ ุจุงู„ู€ Reference ู„ู„ู€ Class ุฃุดุงูˆุฑ ุนู„ู‰ ู†ูุณ ุงู„ู€ Class ุฃูˆ Child ู„ู‡
// Parent      Child
TypeA T1 = new TypeB(1, 2);
// Reference from Parent --> Object from Child
  • ู…ุด ุจูŠุดูˆู ุบูŠุฑ ุงู„ุฌุฒุก ุงู„ู„ูŠ ุงู„ุฅุจู† ูˆุงุฑุซู‡ ู…ู† ุงู„ุฃุจ ุจุณ ุบูŠุฑ ูƒุฏุง ู…ุจูŠุดูˆูุด
  • ู‡ูˆ ุนุจุงุฑุฉ ุนู† Reference Type
    • ุงู„ู€ Reference ุงู„ู„ูŠ ู‡ูˆ ุงู„ุนู†ูˆุงู† ู‡ูŠุฑูˆุญ ููŠ ุงู„ู€ Stack ูˆุงู„ู€ Object ู†ูุณู‡ ุฃูˆ ุงู„ู‚ูŠู…ุฉ ููŠ ุงู„ู€ Heap
TypeA T1 = new TypeB();
// Reference   Object
// Address     Value
// Stack       Heap

Override

  • ุนุฑูู†ุง ุงู† ููŠู‡ ุทุฑูŠู‚ุชูŠู† ู„ู„ู€ Override ู‡ู†ุง Override ุงู„ู€ Static Binding (Early Binding):
  • ู„ูˆ ุนู…ู„ุช override ุนู† ุทุฑูŠู‚ new ู‡ูŠู†ูุฐ ุฃูˆู„ Function ุนู†ุฏูŠ ุจุชุงุน ุงู„ู€ Parent ู…ุด ู‡ูŠุดูˆู ุงู„ู€ Override ุงู„ุฌุฏูŠุฏุฉ ูˆู‡ูŠุนุชุจุฑ ุฏูŠ Function ุฌุฏูŠุฏุฉ ุจูŠู†ูุฑุฏ ุจูŠู‡ุง ุงู„ู€ Child
  • Compiler will bind function call based on Reference Type NOT Object Type at compilation Time ุงู„ู€ Dynamic Binding:
  • ุฅู†ู…ุง ู„ูˆ ุจูƒู„ู…ุฉ override ู‡ูŠู†ูุฐ ุงู„ู„ูŠ ุงู†ุช ุนู…ู„ุชู‡ ูุงู„ุฃุฎุฑ ูˆู‡ูŠู†ูุฐู‡ุง (ุจุชุงุน ุงู„ุฅุจู†)
  • CLR will Bind Function Call based on Object Type NOT Reference Type at Run Time

Not Binding

ู…ุซุงู„:

  • ู„ูˆ ุนู†ุฏูŠ ูƒู„ุจ ุฃู‚ุฏุฑ ุฃู‚ูˆู„ ุนู„ูŠู‡ ุฅู†ู‡ ุญูŠูˆุงู†
  • ุจุณ ู…ุด ูƒู„ ุญูŠูˆุงู† ู‡ู‚ุฏุฑ ุฃู‚ูˆู„ ุนู„ูŠู‡ ุงู†ู‡ ูƒู„ุจ
  • ุนุดุงู† ูƒุฏุง ูƒู†ุง ุจู†ุณุชุฎุฏู… Type Casting in CSharp ููŠ ุงู„ุญุงู„ุฉ ุงู„ู„ูŠ ุฒูŠ ุฏูŠ
// Dog = Animal // ู…ู‚ุฏุฑุด
// Dog = (Dog) Animal // ุงู„ุญูŠูˆุงู† ุฏุง ุจูˆุนุฏูƒ ุงู†ู‡ ูƒู„ุจ
 
object O1 = 3;
 
// int x = O1; // ERROR
// Cause
// O1 = "Ahmed"; // Object can be anything
int x = (int) O1; // ุจูˆุนุฏูƒ ู‡ูŠุจู‚ุง ุงู†ุชุฌุฑ
// (int): built-in casting operator
 
TypeA T1;
T1 = new TypeA(1);
T1 = new TypeB(1, 2); // Child -> Binding
 
TypeB = T2;
T2 = new TypeA(); // ERROR
T2 = T1; // ERROR
T2 = (TypeB) T1; 
// ุจูˆุนุฏูƒ ุงู†ู‡ ู‡ูŠุจู‚ุง ุงู„ุฅุจู† ุฏุง ุจุงู„ุฐุงุช ู„ุฃู† ู‡ูˆ ุนู†ุฏู‡ ุฃุจู†ุงุก ูƒุชูŠุฑ
// This is NOT Binding
 
// (TypeB): We need to make this casting operator

ุงู„ู…ูˆุถูˆุน ุฏุง ู…ุฑุชุจุท ุจุงู„ู€ Cs Casting Operator ุดูˆูŠุฉ ู„ุฃู† ู„ุงุฒู… ุฃุนู…ู„ Casting Operator ู„ู„ุฅุจู† ู„ู…ุง ุจุฎู„ูŠู‡ ูŠุงุฎุฏ Object ุฃุจ ู„ุฃู† ููŠู‡ ุญุงุฌุฉ ุฒูŠุงุฏุฉ ุจุชุจู‚ุง ู…ูˆุฌูˆุฏุฉ ู…ุซุงู„: ุงู„ุฃุจ ุนู†ุฏู‡ A ูˆุงู„ุฅุจู† ูˆุฑุซู‡ ู…ู†ู‡ ูˆูƒู…ุงู† ุฒูˆุฏ B ุฃู†ุง ุฏู„ูˆู‚ุชูŠ ู‡ุนู…ู„ ุงุจู† ู…ู† Object ุฃุจ ุจุณ ุงู„ุฅุจู† ุงู„ู…ูุฑูˆุถ ูŠุนุฑู ุงู„ุญุงุฌุฉ ุงู„ุฒูŠุงุฏุฉ ุจุชุงุนุชู‡ ู‡ุชุจู‚ุง ุจุฅูŠู‡

Example

Example 1

internal class Employee
{
	public int id { get; set; }
	public string name { get; set; }
 
	public void MyFunc01()
	{
		Console.WriteLine("I am Employee");
	}
 
	public virtual void MyFunc02()
	{
		Console.WriteLine($"ID: {id}, Name: {name}");
	}
}
 
class FullTimeEmployee : Employee
{
	public int salary { get; set; }
	public new void MyFunc01()
	{
		Console.WriteLine("I am FullTime Employee");
	}
	public override void MyFunc02()
	{
		Console.WriteLine($"ID: {id}, Name: {name}, Salary: {salary}");
	}
}
class PartTimeEmployee : Employee
{
	public int HoursOfWork { get; set; }
	public new void MyFunc01()
	{
		Console.WriteLine("I am PartTime Employee");
	}
	public override void MyFunc02()
	{
		Console.WriteLine($"ID: {id}, Name: {name}, HoursOfWork: {HoursOfWork}");
	}
}
 
// We will try to make function for them
public void ProcessEmployee(FullTimeEmployee emp)
{
	emp.MyFunc01();
	emp.MyFunc02();
}
public void ProcessEmployee(PartTimeEmployee emp)
{
	emp.MyFunc01();
	emp.MyFunc02();
}
// ุฏุง ู…ุด ุงูˆูุฑู„ูˆุฏูŠู†ุฌ ุฏุง ุนูƒุŒ ู„ุฃู† ุงู„ุฅุชู†ูŠู† ู†ูุณ ุงู„ุจูˆุฏูŠ
// The solution here is BINDING
public void ProcessEmployee(Employee emp)
{
    emp.MyFunc01();
    emp.MyFunc02();
}

Example 2

  • ุฎุฏ ุจุงู„ูƒ ู…ู† ุงู†ู‡ ู‡ูŠู†ูุฐ ุขุฎุฑ Override ูƒุงู† ู…ูˆุฌูˆุฏ ู„ูˆ ุงุณุชุฎุฏู…ุช ุงู„ู€ Static Binding
class TypeA
{
    public int A { get; set; }
 
    public TypeA(int _A=0) { A = _A; }
 
    public void StaticallyBindedShow ()
    {
        Console.WriteLine("I am Base");
    }
    ///Dynamically Binded
    internal virtual void DynShow () ///non Private Virtual Method
    {
        Console.WriteLine($"Base {A}");
    }
}
 
class TypeB:TypeA
{
    public int B { get; set; }
    public TypeB(int _A =0 , int _B=0):base(_A)
    {
        B = _B;
    }
 
    internal override void DynShow()
    {
        Console.WriteLine($"Derived {A} {B}");
    }
 
    public new void StaticallyBindedShow() { 
		    Console.WriteLine("I am Derived"); 
		}
}
 
class TypeC : TypeB
{
    public int C { get; set; }
 
    public TypeC(int _a=0 , int _b=0 , int _c=0):base(_a , _b)
    {
        C = _c;
    }
 
    internal override void DynShow()
    {
        Console.WriteLine($"Type C {A} {B} {C}");
    }
}
 
class TypeD : TypeC
{
    //internal new void DynShow() 
    /// new statically binded impelementation
    
    /// new dynamically binded impelementation
    internal new virtual void DynShow() 
    {
        Console.WriteLine("Type D");
    }
}
class TypeE: TypeD
{
    ///override on TypeD Implementation
    internal override void DynShow()
    {
        Console.WriteLine("Type E");
    }
}
 
class program
{
		static void Main(string[] args)
		{
		  TypeA BaseRef = new TypeA(1);
          BaseRef.StaticallyBindedShow(); ///Base
          BaseRef.DynShow(); ///Base
 
          TypeB DerivedRef = new TypeB(2, 3);
          DerivedRef.StaticallyBindedShow(); ///Derived
          DerivedRef.DynShow(); ///Derived
 
          BaseRef = new TypeB(4, 5);
          ///Ref to Base = Derived Object
          //BaseRef.A = 6;
          BaseRef.StaticallyBindedShow();///Base
          ///Statically Binded methods (non virtual) 
          //Compiler Bind Call based in Refrence Type not Object Type
          BaseRef.DynShow();///Derived
          ///Dynamically Binded Method , CLR will bind Function 
          //Call based on Object Type in Runtime  
 
 
          BaseRef = new TypeC(6, 7, 8);
          DerivedRef = new TypeC(9, 10, 11);
 
          BaseRef.DynShow(); ///TypeC
          DerivedRef.DynShow(); ///TypeC
 
 
          BaseRef = new TypeD();
          BaseRef.DynShow(); ///TypeC
 
 
          TypeD RefD = new TypeD();
          RefD.DynShow(); ///TypeD
		}
}