Intermediate · Inheritance, interfaces and records · topic 20 of 43 · 30 min
Interfaces: contracts for behaviour
Explanation
Why interfaces?
A class can inherit from only one base class, but objects often have several unrelated abilities. A PDF report can be printed, emailed and saved. An interface describes one ability. Any class, from any family tree, can sign the contract by implementing it.
Declaring and implementing
public interface INotifier
{
bool Send(string to, string message);
}
public class SmsNotifier : INotifier
{
public bool Send(string to, string message)
{
Console.WriteLine($"SMS to {to}: {message}");
return true;
}
}
public class EmailNotifier : INotifier
{
public bool Send(string to, string message)
{
Console.WriteLine($"Email to {to}: {message}");
return true;
}
}Programming to an interface
var service = new OrderService(new SmsNotifier());
service.PlaceOrder("Asha", "98xxxxxx10");
public class OrderService
{
private readonly INotifier _notifier;
public OrderService(INotifier notifier) => _notifier = notifier;
public void PlaceOrder(string customer, string phone)
{
// ... save the order ...
_notifier.Send(phone, $"Thanks {customer}, your order is confirmed");
}
}Several interfaces at once
public interface IPrintable { string Print(); }
public interface IExportable { byte[] ToPdf(); }
public class Invoice : IPrintable, IExportable
{
public string Print() => "Invoice #2041";
public byte[] ToPdf() => Array.Empty<byte>(); // placeholder
}Built-in interface 1: IComparable<T>
Array.Sort and List.Sort need to know how to order your objects. Implement IComparable<T>: CompareTo returns a negative number if this comes first, 0 if equal, and a positive number if this comes after.
var list = new List<Student> { new("Ravi", 72), new("Asha", 91), new("Meena", 85) };
list.Sort();
foreach (var s in list) Console.WriteLine($"{s.Name} {s.Marks}");
public class Student : IComparable<Student>
{
public string Name { get; }
public int Marks { get; }
public Student(string name, int marks) { Name = name; Marks = marks; }
// higher marks first
public int CompareTo(Student? other) => other is null ? -1 : other.Marks.CompareTo(Marks);
}Built-in interface 2: IDisposable and using
Some objects hold resources outside .NET's memory: open files, network connections, database connections. They implement IDisposable, which has one method, Dispose(), that releases the resource. A using statement calls Dispose automatically at the end, even if an exception happens.
using (var writer = new StreamWriter("log.txt"))
{
writer.WriteLine("Started");
} // writer.Dispose() runs here: the file is closed
using var reader = new StreamReader("log.txt"); // C# 8 using declaration
Console.WriteLine(reader.ReadLine()); // disposed at the end of the scopeBuilt-in interface 3: IEnumerable<T>
Anything that can be looped with foreach implements IEnumerable<T>: arrays, List<T>, Dictionary and more. LINQ (module 6) is built on it. Taking IEnumerable<T> as a parameter lets callers pass any of these.
Default interface methods (C# 8), briefly
An interface may give a member a default body, so adding a new member later does not break every existing class. It is mainly used by library authors. In your own code, keep interfaces small and simple.
Abstract class or interface?
| Abstract class | Interface | |
|---|---|---|
| How many per class | One | Many |
| Fields and constructors | Yes | No instance fields or constructors |
| Shared code | Yes, normal methods | Only default methods (limited) |
| Meaning | "is a kind of" with shared code | "can do" an ability |
| Example | abstract class Payment | interface INotifier, IComparable<T> |
Common mistakes and fixes
- Huge interfaces with 20 members: classes must implement all of them. Split them into small, focused interfaces.
- Forgetting public on the implementing method: the class method must be public to implement an interface member implicitly.
- Not disposing: a StreamWriter that is never disposed may not write all its data. Use using.
- Creating an interface for every class "just in case": add one when you have two implementations or need a fake for testing.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Interfaces: contracts for behaviour · 1/7
In this lesson you will define contracts with interfaces.
Prefer a video by a teacher? Find free videos on “C# interfaces explained IComparable IDisposable abstract class vs interface” on YouTube ↗
In real life: Switching SMS providers without touching business code
A clinic appointment app in Kochi sends reminders by SMS. When the SMS provider raises prices, the team writes a new class for a cheaper provider that implements the same IReminderSender interface. The appointment code does not change at all.
IReminderSender sender = new ProviderB(); // was: new ProviderA()
var reminders = new ReminderService(sender);
reminders.Remind("Meena", "9:30 AM");
public interface IReminderSender { void SendText(string to, string text); }
public class ProviderA : IReminderSender
{
public void SendText(string to, string text) => Console.WriteLine($"[A] {to}: {text}");
}
public class ProviderB : IReminderSender
{
public void SendText(string to, string text) => Console.WriteLine($"[B] {to}: {text}");
}
public class ReminderService
{
private readonly IReminderSender _sender;
public ReminderService(IReminderSender sender) => _sender = sender;
public void Remind(string patient, string time) => _sender.SendText(patient, $"Your appointment is at {time}");
}Practice (0/4 done)
How many interfaces can one class implement?
What does a using statement guarantee for an IDisposable object?
a.CompareTo(b) returns a negative number. What does that mean for sorting?
Define an interface IDiscount with decimal Apply(decimal amount). Implement PercentDiscount (constructor takes a percent) and FlatDiscount (constructor takes rupees, never going below 0). Write a method Checkout(decimal amount, IDiscount discount) and call it with both.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Records and pattern matchingInheritance, interfaces and records · same module
- Inheritance: base and derived classesInheritance, interfaces and records · same module
- InterfacesJava Programming (Core to Spring Boot) · Inheritance, polymorphism and interfaces
- The C# and .NET interview questions asked most oftenInterviews, portfolio and careers
- Inheritance and interfacesKotlin and Android App Development · Classes, objects and collections
- Abstract classes, interfaces and good class designC++ Programming (modern C++ and DSA) · Operator overloading, inheritance and polymorphism
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What does an interface contain (in the usual case)?
Answer: Member signatures that implementing classes must provide
An interface is a contract of members.
Which is a good reason to depend on an interface?
Answer: You can swap implementations (real, cheaper, fake for tests) without changing the caller
Loose coupling is the main benefit.
Which interface makes foreach work on a type?
Answer: IEnumerable<T>
foreach works on IEnumerable/IEnumerable<T>.
A class implements an interface but misses one member. What happens?
Answer: Compile error CS0535
Every interface member must be implemented.
Which is TRUE?
Answer: A class can inherit one class and implement many interfaces
Single class inheritance, multiple interfaces.
How many interfaces can a class implement?Related
What is an extension method?Related
Answer: A static method whose first parameter uses this, callable like an instance method
LINQ methods are extension methods on IEnumerable<T>.
Can an interface function have a default body in Kotlin?Related
Can an abstract class have a constructor and data members?Related
Answer: Yes; it just cannot be instantiated on its own
Abstract only means "cannot be created directly". It may still hold shared data and constructors for derived classes.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 1 more topic in “Inheritance, interfaces and records” before its exam: Records and pattern matching.
- Module 5 exam: Inheritance, interfaces and records · 13 questions · 20 min, without help. 4 topics of this module still to finish first.
- Then the next module, Collections, generics and LINQ. 43 topics left in the course before the final exam.