Interfaces in C# started as a pure contract type and gradually gained more capabilities across language versions. Here’s a timeline of the major additions.
| C# Version | Interface Feature Added | Example |
| C# 1.0 (2002) | Basic interfaces | Method/property/event/indexer declarations |
| C# 2.0 | Generic interfaces | IEnumerable<T> |
| C# 3.0 | No major interface changes | — |
| C# 4.0 | Generic variance | out, in |
| C# 5–7.x | Minor improvements | Expression-bodied members support |
| C# 8.0 | Default interface implementations | Method body inside interface |
| C# 8.0 | Static members allowed (with bodies) | Static helper methods |
| C# 8.0 | Access modifiers inside interface | private, protected, etc. |
| C# 11 | Static abstract members | Generic math |
| C# 11 | Static virtual members | Default static behavior |
1. C# 1.0 — Interfaces as pure contracts
- Only declarations were allowed.
- No fields, no implementation.
- abstract methods, properties, events and indexers
- Implementation required in implementing class/struct
interface IShape
{
void Draw();
int Points { get; }
}
class Circle : IShape
{
public int Points => 0;
public void Draw()
{
}
}
{
void Draw();
int Points { get; }
}
class Circle : IShape
{
public int Points => 0;
public void Draw()
{
}
}
2. C# 2.0 — Generic interfaces
- Interfaces became type-safe.
- Type parameter introduced with interface type and its members
interface IRepository<T>
{
void Add(T item);
}
{
void Add(T item);
}
Example:
IEnumerable<int>
IComparer<string>
3. C# 4.0 — Variance (in, out)
- Allowed covariance and contravariance.
- in and out modifier with type parameter
- The out modifier tells that the type parameter is return type
- The in modifier tells that the type parameter is method parameter type
- If in or out modifier is omitted then type parameter can be (return type)/(parameter type)
interface IProducer<out T>
{
T Create();
}
Contravariant (in) → parameter types:
interface IConsumer<in T>
{
void Consume(T item);
}
4. C# 8.0 — Default Interface Methods (major change)
- Interfaces could finally contain implementations.
- This will be default implementation for implementers(class/struct)
interface ILogger
{
void Log(string msg)
{
Console.WriteLine(msg);
}
}
Implementers can inherit default behavior:class FileLogger : ILogger
{
}
This helped version interfaces without breaking existing code.
5. C# 8.0 — Access modifiers in interfaces
Before C# 8:
interface ITest
{
void Show(); // implicitly public
}
After C# 8:
interface ITest
{
public void Show()
{
}
private void Helper()
{
}
}
👉public interface members became valid only once interfaces could contain implementations.
6. C# 8.0 — Static members in interfaces
interface IMath
{
static int Add(int a, int b)
{
return a + b;
}
}
{
static int Add(int a, int b)
{
return a + b;
}
}
Used like: IMath.Add(10, 20);
7. C# 11 — Static abstract members (very important)
- Interfaces can require static members.
{
static abstract T operator +(T a, T b);
}
Implementation:
struct Number : IAddable<Number>
{
public int Value;
public static Number operator +(Number a, Number b)
=> new Number { Value = a.Value + b.Value };
}
{
public int Value;
public static Number operator +(Number a, Number b)
=> new Number { Value = a.Value + b.Value };
}
👉This enabled generic math.
8. C# 11 — Static virtual members
interface IExample
{
static virtual int Value => 100;
}
Allows default static behavior.
Overall evolution
- Contract only(abstract declarations of method/property/event/indexer)
- Generic contracts(introduced type parameter T)
- Variance support (in and out modifiers)
- Interfaces with behavior (default methods and access modifier with members)
- Static polymorphism (generic math)
No comments:
Post a Comment