C# Interface

Theodorus DoniTheodorus Doni
6 min read

Introduction

Hello all, today I back with another C# topic, and today I will share what i learned about C# Interface. I hope with this article you will know more about C# Interface and use it on your project.

What It Is?

An interface can be thought of as a contract. This term is used because a class or struct that implements an interface is obligated to provide implementations for all of its members. For instance, if an interface have a method called Attack(), any class or struct that implements this interface must provide its own implementation of the Attack() method.

Why Implement It?

There are several pros and cons to consider before implement an interface in our project. Here are some of them:

Pros

  • Enhance code scalability.

  • Enhance code reusability.

  • Loose coupling between modules.

Cons

  • Could potentially increase the amount of redundant code.

  • It may be challenging for new programmers to understand.

  • When adding a new contract, it's essential to implement it across all classes that inherit from it. This ensures that as more classes connect, the complexity of the system increases appropriately.

How It Works?

To understand how interface work in the system, let's implement it first. To implement an interface, all you need to do is create a class file. However, instead of using the class keyword, you should use the interface keyword, as shown in the code below:

using System;

namespace Lncodes.Example.Interface;

public interface IDamageable
{
    int Health { get; }
    event Action OnHealthRunsOut;
    void TakeDamage(int amountDamage);
}

In the code above, I have created an interface with a Health property, an OnHealthRunsOut event, and a TakeDamage() method. This interface is designed for any class that needs to handle damage-related interactions, such as, Enemy, Player, NPC. After implementing this interface in the code, here's what will happen in the system:

  1. When a class or struct implements an interface, the system will generate an error if that class or struct does not implement all the interface members.

  2. When creating an interface as a variable type, the system will allow assigning objects of all classes or structs derived from this interface to the declared type, such as IDamageable _damageable = new Enemy() or new Player() or new Npc().

Console Application

In my console application, interfaces are used to specify creature capabilities. One interface specifies which creatures can take damage, while another specifies which creatures can attack others. In this console application, both the player and the enemy can take damage and attack other creatures, whereas the NPC can only take damage.

Below is a list of the interfaces and classes I used to create this console application, along with a brief explanation of each interface and class:

Interface And ClassDescription
IAttackerThis interface is used to define a contract for creatures that capable of attacking other creatures. It provides the necessary methods and properties for handling attack-related operations.
IDamageableThis interface is used to define a contract for creatures that capable of taking damage. It provides the necessary methods and properties for handling damage-related operations.
EnemyController, PlayerControllerThese classes are used to implement the IAttacker and IDamagebale interface contract.
NpcControllerThis class is used to implement IDamageable interface contract.
ProgramThis class is used to displaying the attack process of the attackable creature attacking the damageable creature until the damageable creature is defeated on the console.

In the video above, you'll notice that each creatures has its own unique default health points. Additionally, when the enemy or player attack there's difference implementation on how they attack, the enemy sometimes miss the attack but the player never miss the attack and the damage points they have are also different from each other.

By implementing interfaces, the behaviors and attributes of creatures are clearly defined and managed. Interfaces provide specific rules for what each creature can do and what properties it should have. This leads to more organized and maintainable code by establishing a consistent structure, which makes it easier to update or add new features.

The source code for this console application can be viewed and downloaded at Project Repository – Github.

Additional Information

I have discovered some additional information about C# Interface. If you have any additional information about C# Interface that you'd like to share, please feel free to leave a comment.

Naming Guidelines

When implementing interfaces, following specific naming guidelines can help ensure code readability and consistency. Here are some naming conventions recommended by Microsoft:

  • Use adjective phrases, or occasionally nouns or noun phrases, when naming interfaces e.g. IDamageable, IPlayer.

    Nouns and noun phrases should be used rarely for interface names. Frequent use might indicate that the interface could be more appropriately represented as an abstract class or a regular class.
  • Do use 'I' prefix when naming interfaces e.g. IAttacker, IDamageable.

Interface VS Abstract

Both interfaces and abstract classes offer similar functionality for enhancing code abstraction by defining contracts or blueprints for derived classes. Due to these similarities, choosing between them can be challenging. Here are some key factors to consider before making a decision:

  • Use an interface when its member functionality is designed to be used by multiple modules. For example, when creating an IDamageable interface, the functionality of its members is intended to be used across various modules, including player, NPC, and enemy modules. This inclusivity makes it ideal to use an interface rather than an abstract class.

  • Interface can't have methods with default implementations, but abstract class can have methods with default implementations.

    Since C# 8, interface can have methods with default implementations. However, the object of the derived class can't call this method unless the derived class overrides it first.
  • The only access modifier that can be used for the interface members is public. The private, protected, and internal access modifiers can't be used for the interface members. However, all access modifiers can be used in the abstract class members.

    Since C# 8, interface members can use the private, protected, or internal access modifier.
  • Interfaces can't have variables as a member, but abstract classes can have them as a member.

  • A class can inherit from multiple interfaces, but it can't inherit from multiple abstract classes.

  • A struct can inherit from an interface, but it can't inherit from an abstract class.

💡
To learn more about C# Abstract, check out my post at C# Abstract - Last Night Codes.

Further Discoveries

Here are some further discoveries I have gathered from various sources that may provide a deeper understanding of C# Interface:

  • The interface can't be instantiated.

  • Struct can inherit from an interface.

  • Interface can only have method, property, or event as a member.

  • If a class or struct implements an interface but does not fully utilize all of its contract, that interface needs to be divided into several smaller interfaces. This is necessary to avoid violating the Interface Segregation Principle (ISP), which is a key tenet of the SOLID principles.

  • An interface can be explicitly declared in its derived class, for example: public int IDamageable.Health {get;}.

  • Never create an interface if the interface doesn't have any members.

Reference

  1. C# Interface – Microsoft

  2. C# Interface Naming Guidelines - Microsoft

0
Subscribe to my newsletter

Read articles from Theodorus Doni directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Theodorus Doni
Theodorus Doni