Recently I've posted a question on reddit - what is the most difficult for you to understand when you're learning C#? https://www.reddit.com/r/learncsharp/comments/lqpo4i/what_is_the_most_difficult_for_you_to_learn_c/
One of the things that you guys have mentioned was interfaces. Let's put some light on interfaces and their purpose.
What is an interface?
You can think about an interface as a contract that the class implementing that interface has to fulfill. We can say that interface tells us WHAT needs to happen. The class needs to "worry" about HOW to do it. Interface can declare property, event, or method.
public interface ISampleInterface
{
string Name { get; set; } // Property
event Action SomethingHappened; // Event
int Add(int a, int b); // Method
}
Example
Let's take a look at the INotification interface.
interface INotification
{
void Send(string message);
}
It has only one method declared. The method is Send, which takes message parameter, type of string. Its purpose is to mark the class that implements its interface as a class that can Notify a user about something, by sending a message.
Let's take Email Notifications on the wallpaper.
class EmailNotification : INotification
{
public void Send(string message)
{
// code responsible for sending email
}
}
The interface is forcing EmailNotification class to implement (write code to execute) Send method. Class implementing an interface has to have exactly the same method declaration.
Does the INotification interface care about the technical details of how the email notification is sent?
Nope, it doesn't. All it has to do is to make sure that this class declares to have the method that is contained in the interface. Technical details are not important. The implementation can be either written by a developer or delegated to an external library.
The important thing is that the class implementing INotification interface declares that it'll send a message to the user, somehow. Class implementing an interface provides an implementation of declared functionalities.
Let's look at example usage. Something happened in the system and it should notify the user about that with some kind of message. Notification preferences normally would be taken from some kind of storage, like a database. For this example, I just used a manually initialized list.
Notice that I am able to initialize a list with the type of Interface that has been declared. Classes implementing this interface can be added to such a list. Thanks to that, in foreach loop, I can execute .Send(string message) method declared by the interface. In effect, user would be notified of every preferred notification method.
static void Main(string[] args)
{
var notificationPreferences = GetUsersNotificationPreferences();
foreach (var notificationPreference in notificationPreferences)
{
notificationPreference.Send(args[0]);
}
}
static List<INotification> GetUsersNotificationPreferences()
{
// This should come from user's preferences,
// which could be stored in database for example
return new List<INotification>
{
new EmailNotification(),
new SmsNotification(),
new PushNotification()
};
}
Default implementation
Since C# 8.0 an interface may provide a default implementation. It may also define static members in order to provide a single implementation for common functionality.
public interface ILogger
{
void Log(string message) => Console.WriteLine($"Log: {message}");
}
I am programming mostly in medium-large scale business web applications and we haven't really used it too much. My recommendation is not to abuse it and think twice about whether you really need to have a default implementation.
Class can implement multiple interfaces
One class can implement multiple interfaces.
class EmailNotification : INotification, ILogger
{
public void Send(string message)
{
// code responsible for sending email
}
public void Log(string message)
{
Console.WriteLine($"Email sent with message: {message}");
}
}
Interface can implement another interface
interface INotification : ILogger
{
void Send(string message);
}
Then every class implementing that interface needs to implement the other one as well.
Ok, but how does it help me? Do I really need to split things into WHAT (interface) and HOW (class) to do my project? Well... Interfaces are part of something bigger. But to give you one small example. If you've heard about Dependency Injection you may recall that abstractions should not depend on details. For a simple example, think about architecture with layers. Let's say that there are only two layers, outer and inner. The outer layer declares an interface saying that I need you (the inner layer) to do something. For example, send an email. An engine that is responsible for running the application starts executing a piece of code of the outer layer that declares the need to send an email. Then, it looks for implementation of that interface, so a class that knows how to send an email. How does the "engine" know what class to provide here? It's all set up in something called dependency injection's container, but that's definitely for another topic.
Those are the next steps. I hope I've been able to make interfaces at least a little bit more understandable.
Is there something else that bothers you about interfaces?
Top comments (1)
Thanks for the comment, Sebastian 🙏
Thanks for adding that. It's an important aspect of C#.
Great example.