Inheritance →
class Parent
{
public int X { get; protected set; }
public int Y { get; protected set; }
public Parent(int _X , int _Y)
{
X = _X;
Y = _Y;
Console.WriteLine("Base Ctor");
}
public int Product() { return X * Y; }
public override string ToString()
{
return $"({X},{Y})";
}
}
class Child:Parent
{
public int Z { get; protected set; }
public Child(int _X , int _Y , int _Z)
:base(_X,_Y) ///Base Ctor Chaining
{
Z = _Z;
Console.WriteLine("Child Ctor");
}
public new int Product ()
{
return Z * base.Product();
//return X * Y * Z;
}
public override string ToString()
{
return $"{X},{Y},{Z}";
}
}
class program
{
static void Main()
{
Parent P = new Parent(1, 2);
Console.WriteLine(P.Product());
Child C = new Child(3, 4, 5);
Console.WriteLine(C.Product()); ///Derived
///Not Valid C# Code
//keyword base used only inside Derived class not Outside
//Console.WriteLine(C.base.Product() );
}
}
Abstract Class →
//class created to be base class for childs
// can't intialize object from abstract class
abstract class Person
{
public string FName { get; set; }
public string LName { get; set; }
public Person(string _FName , string _LName)
{
FName = _FName;
LName = _LName;
}
public override string ToString()
{
return $"{FName} {LName}";
}
}
//valid
Person P;
//not Valid
//Person P1 = new Person("Ahmed", "Ali");
abstract class GeoShape
{
public int Dim1 { get; set; }
public int Dim2 { get; set; }
public GeoShape(int D1 , int D2) { Dim1 = D1; Dim2 = D2; }
//public virtual Double Area () =0; //C++
public abstract Double Area();
///Abstract Method = Virtual + No Impelementation
public abstract double Perimeter { get; /*set;*/ }
///Abstract ReadOnly Property
}
abstract class RectBase : GeoShape
{
public RectBase(int W=0, int H=0) : base(W, H) { }
public override double Area()
{
return Dim1 * Dim2;
}
}
class Rect : RectBase
{
public override double Perimeter { get { return 2 * (Dim1 + Dim2); } }
}
class Square : RectBase
{
///Must
// because perimeter didn't implemented in rectbase
public override double Perimeter => 4 * Dim2;
///Optional
// because Area implemented in rectbase
public override double Area()
{
throw new NotImplementedException();
}
}
Equality →
Class Equality →
public class Point:IComparable<Point>
{
public int X { get; set; }
public int Y { get; set; }
public int CompareTo( Point other)
{
if (other == null) return 1;
if (X == other.X)
return Y.CompareTo(other.Y);
return X.CompareTo(other.X);
}
public override bool Equals(object obj)
{
#region Casting
//Point Right = (Point)obj; /// unSafe Casting
//if (obj is Point) ///is -> return false if casting
//will Fail , no exceptions will be thrown
//{
// Point Right = (Point)obj;
// return (X == Right.X) && (Y == Right.Y);
//}
//if (obj is Point Right) ///is return false if
//casting will Fail , no exceptions will be thrown
// return (X == Right.X) && (Y == Right.Y);
//return false;
#endregion
Point Right = obj as Point; ///as -> return null if
//Casting Fails , no exception will be thrown
if (Right == null) return false;
if (this.GetType() != obj.GetType()) return false;
if (object.ReferenceEquals(this, Right)) return true;
return (X == Right.X) && (Y == Right.Y);
}
public override string ToString()
{
return $"({X},{Y})";
}
}
class program
{
static void Main(string[] args)
{
Point P1 = new Point() { X = 5, Y = 10 };
Point P2 = new Point() { X = 5, Y = 10 };
Point P3 = P1;
Point3D P4 = new Point3D() { X = 5, Y = 10, Z = 15 };
//P2 = default;
if (P1.Equals(P4))
Console.WriteLine("P1 EQ P4");
else
Console.WriteLine("P1 NEQ P4");
if (P1.Equals(P2))
Console.WriteLine("P1 EQ P2");
else
Console.WriteLine("P1 NEQ P2");
if (P1.Equals(P3))
Console.WriteLine("P1 EQ P3");
else
Console.WriteLine("P1 NEQ P3");
int X = 5;
Console.WriteLine(object.ReferenceEquals(X, X));
}
}
Struct Equality →
Virtual Methods and Classes →
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
}
}
Generic Method in non Generic Class →
class Helper
{
#region Non Generic Swap
//public static void SWAP ( ref int X , ref int Y)
//{
// int Temp = X;
// X = Y;
// Y = Temp;
//}
//public static void SWAP(ref double X, ref double Y)
//{
// double Temp = X;
// X = Y;
// Y = Temp;
//}
//public static void SWAP(ref string X, ref string Y)
//{
// string Temp = X;
// X = Y;
// Y = Temp;
//}
#endregion
///Generic Method in non Generic Class
public static void SWAP<T>(ref T X, ref T Y)
{
T Temp = X;
X = Y;
Y = Temp;
}
}
Main →
class program
{
static void Main(string[] args)
{
#region Generic Method
int A = 7, B = 3;
Helper.SWAP<int>(ref A, ref B);
///Call Generic Function Explicitly Define T
//Helper.SWAP(ref A, ref B); ///non Generic Function
Console.WriteLine($"A = {A}");
Console.WriteLine($"B = {B}");
double D1 = 1.2345, D2 = 1234.5;
Helper.SWAP(ref D1, ref D2);
///In case of Generic Method (Not Generic Class\\struct\\interface)
///Compiler can Detect Type PAramter T Type from input Parameteres
Console.WriteLine($"D1 {D1}");
Console.WriteLine($"D2 {D2}");
String Str1 = "ABC", Str2 = "XYZ";
Helper.SWAP(ref Str1, ref Str2);
Console.WriteLine($"Str1 {Str1}");
Console.WriteLine($"Str2 {Str2}");
Point P1 = new Point() { X = 10, Y = 20 };
Point P2 = new Point() { X = 30, Y = 40 };
Helper.SWAP(ref P1, ref P2);
Console.WriteLine($"P1 {P1}");
Console.WriteLine($"P2 {P2}");
#endregion
}
}
Generic Method in Generic Class →
class Helper<T>
{
///Generic Method in Generic Class
public static void SWAP(ref T X, ref T Y)
{
T Temp = X;
X = Y;
Y = Temp;
}
}
Main →
class program
{
static void Main(string[] args)
{
int A = 7, B = 3;
Helper<int>.SWAP(ref A, ref B);
Console.WriteLine($"A = {A}");
Console.WriteLine($"B = {B}");
double D1 = 1.2345, D2 = 1234.5;
Helper<double>.SWAP(ref D1, ref D2);
///No Type inference for Generic Class
Console.WriteLine($"D1 {D1}");
Console.WriteLine($"D2 {D2}");
String Str1 = "ABC", Str2 = "XYZ";
Helper<string>.SWAP(ref Str1, ref Str2);
Console.WriteLine($"Str1 {Str1}");
Console.WriteLine($"Str2 {Str2}");
Point P1 = new Point() { X = 10, Y = 20 };
Point P2 = new Point() { X = 30, Y = 40 };
Helper<Point>.SWAP(ref P1, ref P2);
Console.WriteLine($"P1 {P1}");
Console.WriteLine($"P2 {P2}");
}
}
Advantages →