What is Interfaces?

  • ู‡ูˆ ุนุจุงุฑุฉ ุนู† Code contract ุจูŠู† ุงู„ู€ Developer ุงู„ู„ูŠ ูƒุชุจู‡ ูˆุงู„ู€ Developer ุงู„ู„ูŠ ู‡ูŠุนู…ู„ู‡ Implementation
  • Interface โ†’ prototype - code contract - no data in
  • If class follows an interface we must initialize all interface (methods, properties) in the class
  • ุจูŠุชูƒุชุจ ุฌูˆุง ุงู„ู€ Cs Namespace ูˆู‚ูˆู„ู†ุง ุงู„ู…ูˆุถูˆุน ุฏุง ููŠ Inside Namespace
  • ู…ูŠู†ูุนุด ุฃุนู…ู„ Object ู…ู† ุงู„ู€ Interface ุจุณ ูŠู†ูุน ุฃุนู…ู„ Reference ู„ุฃู† ุฃุตู„ู‹ุง ุจูŠุจู‚ุง ููŠู‡ Bodies ุจุณ ูู‡ูˆ ู‡ูŠุนู…ู„ ุงูŠู‡ุŸ
interface IMyType
{
	 int Salary {get; set;}
	 void MyFun();
	 void Print()
	 {
		 Console.WriteLine("Hello World");
	 }
}
  • ุงู„ู„ูŠ ุจูŠุนู…ู„ Implement ู‡ูˆ Cs Class ุฃูˆ Cs Struct: ูŠุนู†ูŠ ู‡ูŠุนุฏูŠ ุนู„ู‰ ูƒู„ Signature ูˆูŠูƒุชุจ ุงู„ู€ Implementation

Practical with classes

  • ุงู„ู€ Reference ู…ู† ุงู„ู€ Interface ูŠู‚ุฏุฑ ูŠุดุงูˆุฑ ุนู„ู‰ Object ู…ู† ุงู„ู€ Class ุจุดุฑุท ุฅู† ุงู„ู€ Class ูŠูƒูˆู† ุจูŠ Implement ุงู„ู€ Interface ูˆุฏูŠ ุงู„ุทุฑูŠู‚ุฉ ุงู„ูˆุญูŠุฏุฉ ุงู„ู„ูŠ ุฃู‚ุฏุฑ ุฃูˆุตู„ ุจูŠู‡ุง ู„ู„ู€ Default implemented method
  • ู…ุจุณุชุฎุฏู… ุงู„ู€ Default implemented method ุบูŠุฑ ููŠ ุญุงู„ุฉ ูˆุงุญุฏุฉ ูˆู‡ูŠ ุงู† ูŠุจู‚ุง ุนู†ุฏูŠ ุฃูƒุชุฑ ู…ู† Class ู„ูŠู‡ู… ู†ูุณ ุงู„ู€ Interface ูˆุจูŠุจู‚ุง ุนู†ุฏู‡ู… Function ู…ุดุชุฑูƒุฉ
  • ู„ู„ูˆู‡ู„ุฉ ุงู„ุฃูˆู„ู‰ ุชุญุณ ุงู„ุนู…ู„ูŠุฉ ุฏูŠ ุดุจู‡ ุงู„ู€ Cs Binding
  • ุจุณุชุฎุฏู…ู‡ุง ููŠ ุงู„ุฃุบู„ุจ ู„ูˆ ุนู†ุฏูŠ Function ุนุงู…ุฉ ู…ุนุฑูุด ู…ู…ูƒู† ูŠุจู‚ุง ููŠู‡ุง ุงูŠู‡ ูˆู…ู…ูƒู† ุชุชุบูŠุฑ ุฒูŠ ู…ุซุงู„ ุงู„ู€ Series ูู…ุซู„ู‹ุง GetNext ู‡ุชุชุบูŠุฑ ูˆุจูŠุจู‚ุง ุฒูŠ ุนู‚ุฏ ูˆุจุฌุจุฑ ุงู„ุดุฎุต ุงู„ู„ูŠ ุจูŠุนู…ู„ู‡ ุงู†ู‡ ูŠู…ุดูŠ ุนู„ู‰ ุงู„ุนู‚ุฏ ุฏุง

Why Interfaces

ุญู„ุช ู…ุดูƒู„ุชูŠู† ุนู†ุฏู†ุง:


Explicitly and Implicitly

  • ู„ูˆ ุนู†ุฏูƒ Class ูˆู‡ูˆ ุจูŠุนู…ู„ Implement ู„ุฃูƒุชุฑ ู…ู† Interface ูˆู‡ู… ููŠู‡ู… Function ู„ูŠู‡ุง ู†ูุณ ุงู„ุฅุณู… ููŠ ุงู„ู€ Interfaces ุฏูŠ ูˆุงู†ุช ุฑูˆุญุช ุนู…ู„ุช Implement ู„ู„ู€ Function ุฏูŠ Implicitly ุณุงุนุชู‡ุง ุงู„ู€ Compiler ุจูŠูุชุฑุถ ุงู† ุงู„ู€ Function ุฏูŠ ู„ู„ุฅุชู†ูŠู†

ุงู„ูุฑู‚ ุจูŠู† ุงู„ู€ Implicitly ูˆ ุงู„ู€ Explicitly:

  • ุงู„ู€ Implicitly: ุจูŠุนุชุจุฑ ุงู„ู€ Function ู„ูˆ ู…ุดุชุฑูƒุฉ ู†ูุณ ุงู„ู€ Implementation ู„ูƒู„ู‡
  • ุงู„ู€ Explicitly: ู„ูˆ ุนุงูŠุฒ ุฃุบูŠุฑ ุงู„ู€ Implementation ู„ู„ูุงู†ูƒุดู† ุงู„ู…ุดุชุฑูƒุฉ ุฏูŠ ู„ุฃูƒุชุฑ ู…ู† Interface ุฎุฏ ุจุงู„ูƒ ุงู„ู€ Function ู…ุชู†ูุนุด ุชุจู‚ุง Public ูˆุฏุงูŠู…ู‹ุง ุจุชุจู‚ุง Private ุงู„ู„ูŠ ู‡ูˆ ุงู„ู€ Default ู„ู„ุญุงุฌุงุช ุฌูˆุง ุงู„ู€ Class ูˆู„ูˆ ุนุงูŠุฒ ุฃูˆุตู„ ู„ู„ู€ Function ุฏูŠ ู„ุงุฒู… ุฃุนู…ู„ Reference ู…ู† ุงู„ู€ Interface ุฏูŠ ูˆุฃุดุงูˆุฑ ุนู„ู‰ Object ู…ู† ุงู„ูƒู„ุงุณ ุงู„ู„ูŠ ุจูŠุนู…ู„ Implementation ู„ู‡

Example

ุนู†ุฏูŠ ุงุชู†ูŠู† Classes ูˆุงุญุฏุฉ ู„ู„ุนุฑุจูŠุฉ ูˆูˆุงุญุฏุฉ ู„ู„ุทูŠุงุฑุฉ ูˆุงู„ุนุฑุจูŠุฉ ุจุชุญุฑูƒ ุนุงู„ุฃุฑุถ ุจุณ ุงู†ู…ุง ุงู„ุทูŠุงุฑุฉ ุจุชุชุญุฑูƒ ููŠ ุงู„ุทูŠุงุฑุฉ ูˆููŠ ุงู„ุฌูˆ ู‡ุชู„ุงู‚ูŠ ุงู† ุงู„ู€ Functions ุจุชุงุน ุงู„ุฅุชู†ูŠู† ู„ูŠู‡ู… ู†ูุณ ุงู„ุฅุณู… ูุจุงู„ุชุงู„ูŠ ู„ุงุฒู… ุฃุณุชุฎุฏู… ุงู„ู€ Explicitly Implement

interface IMoveable
{
    void Forward();
}
 
internal interface IFlyable
{
    void Forward();
}
 
class Car : IMoveable
{
    public void Forward()
    {
        throw new NotImplementedException();
    }
}
 
class Airplane : IMoveable, IFlyable
{
    //public void Forward() // implicit implementation
	//{
	//    throw new NotImplementedException();
	//}
 
	void IMoveable.Forward() // explicit implementation
	{
	    throw new NotImplementedException();
	}
	
	void IFlyable.Forward()
	{
	    throw new NotImplementedException();
	}
}
 
// MAIN
Car c1 = new();
c1.Forward();
 
Airplane a1 = new();
//a1.Forward(); // Cannot call method 'Forward()' because it is Explicitly Implemented
 
IMoveable moveable = new Airplane();
moveable.Forward();

1. Implicit Implementation:

When you implicitly implement an interface, the members of the interface are public members of the class. These members can be accessed directly via an instance of the class, and there is no need to cast the instance to the interface type.

When to use:

  • If you want the interfaceโ€™s members to be directly accessible via the classโ€™s object.
public interface IAnimal
{
    void Speak();
}
 
public class Dog : IAnimal
{
    // Implicit implementation
    public void Speak()
    {
        Console.WriteLine("Woof!");
    }
}
 
class Program
{
    static void Main()
    {
        Dog dog = new Dog();
        dog.Speak();  // No cast required, direct access
    }
}

2. Explicit Implementation:

When you explicitly implement an interface, the members are not directly accessible via an instance of the class. Instead, they can only be accessed by casting the instance to the interface type. This is useful when you want to provide different implementations for the same method name across multiple interfaces or avoid exposing interface members as part of the classโ€™s public API.

  • When to use:
    • If you want to hide the interface methods from being accessed directly through the classโ€™s object.
    • If there are method name conflicts when implementing multiple interfaces.
public interface IAnimal
{
    void Speak();
}
 
public class Dog : IAnimal
{
    // Explicit implementation
    void IAnimal.Speak()
    {
        Console.WriteLine("Woof!");
    }
}
 
class Program
{
    static void Main()
    {
        Dog dog = new Dog();
        // dog.Speak();  // This will give a compilation error
        // To call Speak, cast the object to IAnimal
        ((IAnimal)dog).Speak();  // Casting is required
    }
}

Key Differences:

  • Accessibility:
    • Implicit: Interface methods are accessible directly via the class instance.
    • Explicit: Interface methods are only accessible via a cast to the interface type.
  • Use case:
    • Implicit: Suitable when you want the methods to be part of the classโ€™s public API.
    • Explicit: Suitable when you want to implement multiple interfaces with methods of the same name or when you donโ€™t want the interface methods to be part of the public API.

Simple Example

interface IMyType
{
    public int Salary { get; set; } // Signature of Property
    void MyFunc();
    void Print()
    {
        Console.WriteLine("Hello World");
    }
}
//class MyType : IMyType
//{
//    public int Salary { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
 
//    public void MyFunc()
//    {
//        throw new NotImplementedException();
//    }
//}
 
// => goes to (arrow function) for oneline functions
 
interface IMyType
{
    public int Salary { get; set; } // Signature of Property
    void MyFunc();
    void Print()
    {
        Console.WriteLine("Hello World");
    }
}
class MyType : IMyType
{
    public int Salary { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
 
    public void MyFunc()
    {
        throw new NotImplementedException();
    }
}
 
// MAIN
IMyType T; // Reference to an Interface
//IMyType T2 = new IMyType(); // ERROR -> Cannot create an object of an Interface
IMyType T3 = new MyType(); // OK -> Upcasting from class to Interface
MyType T1 = new MyType();
 
T1.MyFunc();
// T1.Print(); //ERROR -> Cannot call a method of an Interface from class
 
T3.Print(); // OK -> Down casting from Interface to class

Access modifiers

Transclude of Cs-Access-Modifiers#inside-cs-interface-interface
^917dd1

Examples

Example 1

namespace InterfaceEx1
{
		interface ISeries
		{
				int Current { get; }
				void GetNext();
				void Reset();
		}
		class FibSeries : ISeries
		{
				int current;
				int prev;
				public FibSeries()
				{
						prev = 0;
						current = 1;
				}
				public int Current { get { return current; } }
				public void GetNext()
				{
						int Temp = Current;
						current += prev;
						prev = Temp;
				}
				public void Reset()
				{
						current = 1;
						prev = 0;	
				}
		}
			
		struct SeriesByTwo : ISeries
	  {
		    int current;
		    public int Current { get { return current; } }
		
		    public void GetNext()
		    {
			       current += 2;
		    }
		
		    public void Reset()
		    {
			       current = 0;
		    }
	  }
	  
	  class Program
	  {
			  public static void ProcessSeries (ISeries series)
        {
            for ( int i=0; i < 10; i++)
            {
                Console.Write($"{series.Current} , ");
                series.GetNext();
            }
            Console.WriteLine("");
            series.Reset();
        }
        
        static void MainV1(string[] args)
        {
		        SeriesByTwo series01 = new SeriesByTwo();
 
            ProcessSeries(series01);
 
            ISeries series02; ///Valid ,
            //Refrence to any Class\Struct Implementing ISeries Interface
            //series01 = new ISeries(); ///Not Valid
            series02 = new FibSeries();
            ProcessSeries(series02);
        }
	  }  
}

Example 2

namespace D04
{
    interface IMyType
    {
        //int X; Not Supported
 
        void FunOne();
 
        decimal Salary { get; set; }
 
        ///C# 8.0 Feature: Default Implemented Methods
        //internal void FunTwo ()
        //{
        //    Console.WriteLine("Inside Interface");
        //}
    }
 
    struct MyType : IMyType
    {
        public decimal Salary 
        {
            get { return 0; }
            set { }
        }
 
        public void FunOne()
        {
            Console.WriteLine("My Type Fun one");
        }
    }
 
}

Example 3

namespace D04
{
    struct Employee:IComparable
    {
        public int ID;
 
        string Name; 
 
        public string GetName ()
        {
            return Name;
        }
 
        internal void SetName ( string name)
        {
            Name = name.Length <= 20 ? name : name.Substring(0, 20);
        }
 
        decimal salary;
 
        public decimal Salary
        {
            get { return salary; }
            internal set { salary = value >= 1200 ? value : 1200; }
        }
 
        public decimal Deductions
        {
            get { return 0.11M * salary; }
        }
 
        public Employee(int _id , string _Name , decimal _salary)
        {
            ID = _id;
            Name = _Name;
            salary = _salary;
        }
 
        public override string ToString()
        {
            return $"{ID}::{Name}::{salary}";
        }
 
        ///return +ve this > obj
        ///return -ve this < obj
        ///return 0 this == obj
        ///items[j].compareTo(items[j+1]) //Inside Sort
        public int CompareTo(object obj)
        {
            //foreach (var item in (new StackTrace()).GetFrames())
            //    Console.WriteLine(item.GetMethod().Name);
 
            Employee Right = (Employee)obj; //UnBoxing
 
            //if (salary > Right.salary)
            //    return 1;
            //else if (salary < Right.salary)
            //    return -1;
            //else
            //    return 0;
 
            return salary.CompareTo(Right.salary);
        }
    }
    
    class Program
    {
		    static void MainV1(string[] args)
		    {
				    Employee[] EArr = new Employee[3]
            {
                new Employee(5 , "Ahmed Aly" , 17000),
                new Employee(8 , "Sayed Aly" , 5000),
                new Employee(2 , "Mona Aly" , 10000)
            };
 
            Array.Sort(EArr);
 
            foreach (var item in EArr)
            {
                Console.WriteLine(item);
            }
		    }
    }
}

Built-in Interfaces