English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

C# Interface (Interface)

In the human world, a contract between two or more people constrains them to act according to the contract. Similarly, an interface includes declarations of related functions. Entities that implement the interface must provide implementations of the declared functions.

In C#, the interface keyword can be used to define an interface. An interface can contain declarations of methods, properties, indexers, and events. However, it cannot contain fields or auto-implemented properties.

The following interface declares some basic file operation functions.

interface IFile
{
    void ReadFile();
    void WriteFile(string text);
}

You cannot apply an access modifier to interface members. By default, all members are public. If an access modifier is used in an interface, the C# compiler will generate a compile-time error: ‘The modifier ‘public’/private/‘protected’ is not valid for this item. (Visual Studio will immediately display an error without compiling.)

interface IFile
{
    protected void ReadFile(); //Compilation error
    private void WriteFile(string text);//Compilation error
}

Interfaces can only contain declarations and cannot contain implementations. The following will result in a compile-time error.

interface IFile
{
    void ReadFile();
    void WriteFile(string text){
        Console.Write(text);  //Error: Cannot implement method
    }
}

Implementing an Interface

A class or a struct can implement one or more interfaces using a colon (:).  

Syntax:

<Class or Struct Name> : <Interface Name>

For example, the following class implicitly implements the IFile interface.

interface IFile
{
    void ReadFile();
    void WriteFile(string text);
}
class FileInfo : IFile
{
    public void ReadFile()
    {
        Console.WriteLine("Reading File")
    }
    public void WriteFile(string text)
    {
        Console.WriteLine("Writing to file");
    }
}

In the above example, the FileInfo class implements the IFile interface. It defines all members of the IFile interface using the public access modifier. The FileInfo class can also contain members other than interface members.

Interface members must be implemented using the public modifier; otherwise, the compiler will produce a compile-time error.

You can create an object of the class and assign it to a variable of the interface type as shown below.

public class Program
{
    public static void Main()
    {
        IFile file1 = new FileInfo();
        FileInfo file2 = new FileInfo();
        file1.ReadFile(); 
        file1.WriteFile("content"); 
        file2.ReadFile(); 
        file2.WriteFile("content"); 
    }
}

Above, we created an object of the FileInfo class and assigned it to both an IFile type variable and a FileInfo type variable. When an interface is implicitly implemented, you can access IFile members using both the IFile type variable and the FileInfo type variable.

Explicit Implementation

Interfaces can be explicitly implemented using <InterfaceName>.<MemberName>. When a class is implementing multiple interfaces, explicit implementation is useful; therefore, it is easier to read and eliminates confusion. It is also useful if the interfaces have the same method names.

Do not use public Modifiers are used together with explicit implementation. It will result in a compile-time error.
interface IFile
{
    void ReadFile();
    void WriteFile(string text);
}
    
class FileInfo : IFile
{
    void IFile.ReadFile()
    {
        Console.WriteLine("Reading File")
    }
    void IFile.WriteFile(string text)
    {
        Console.WriteLine("Writing to file");
    }
}

When an interface is explicitly implemented, interface members can only be accessed through instances of the interface type.

interface IFile
{
    void ReadFile();
    void WriteFile(string text);
}
class FileInfo : IFile
{
    void IFile.ReadFile()
    {
        Console.WriteLine("Reading File")
    }
    void IFile.WriteFile(string text)
    {
        Console.WriteLine("Writing to file");
    }
    public void Search(string text)
    {
        Console.WriteLine("Searching in file");
    }
}
public class Program
{
    public static void Main()
    {
        IFile file1 = new FileInfo();
        FileInfo file2 = new FileInfo();
        file1.ReadFile(); 
        file1.WriteFile("content"); 
        //file1.Search("text to be searched")//Compilation error 
        
        file2.Search("text to be searched");
        //file2.ReadFile(); //Compilation error 
        //file2.WriteFile("content"); //Compilation error 
    }
}

In the above example, file1The object can only access the members IFile, and file2Can only access the members of the FileInfo class. This is the limitation of explicit implementation.

Implementing multiple interfaces

A class or structure can implement multiple interfaces. It must provide implementations for all members of all interfaces.

interface IFile
{
    void ReadFile();
}
interface IBinaryFile
{
    void OpenBinaryFile();
    void ReadFile();
}
class FileInfo : IFile, IBinaryFile
{
    void IFile.ReadFile()
    {
        Console.WriteLine("Reading Text File");
    }
    void IBinaryFile.OpenBinaryFile()
    {
        Console.WriteLine("Opening Binary File");
    }
    void IBinaryFile.ReadFile()
    {
        Console.WriteLine("Reading Binary File");
    }
    public void Search(string text)
    {
        Console.WriteLine("Searching in File");
    }
}
public class Program
{
    public static void Main()
    {
        IFile file1 = new FileInfo();
        IBinaryFile file2 = new FileInfo();
        FileInfo file3 = new FileInfo();
        file1.ReadFile(); 
        //file1.OpenBinaryFile(); //Compilation error 
        //file1.SearchFile("text to be searched"); //Compilation error 
        
        file2.OpenBinaryFile();
        file2.ReadFile();
        //file2.SearchFile("text to be searched"); //Compilation error 
    
        file3.Search("text to be searched");
        //file3.ReadFile(); //Compilation error 
        //file3.OpenBinaryFile(); //Compilation error 
    }
}

Above, FileInfo implements two interfaces, IFile and IBinaryFile explicitly. It is recommended to explicitly implement interfaces when implementing multiple interfaces to avoid confusion and improve readability.

Key Points to Remember:
  1. Interfaces can contain method, property, indexer, and event declarations.

  2. Interfaces cannot contain private members, protected members, or internal members. By default, all members are public.

  3. Interfaces cannot contain fields or automatically implemented properties.

  4. A class or struct can implicitly or explicitly implement one or more interfaces. Use the public modifier when implicitly implementing an interface, and do not use it in the explicit case.

  5. Explicitly implement an interface using InterfaceName. MemberName.

  6. A single interface can inherit from one or more interfaces.