C# 14: Introducing Extension Members
Introduction
C# continues to evolve with every major release, and C# 14 is no exception.
This time, the language introduces a feature that many developers have been wishing for over the years: extension members.
Until now, C# only allowed extension methods. They were convenient, but also limited. With C# 14, we can finally extend types with properties, methods, and even static members, all grouped under a dedicated extension block.
In this post, we’ll explore how this works, why it matters, and what it means for designing richer, more expressive APIs.
Before C# 14: Extension Methods Only
Before C# 14, if you wanted to extend a type you didn’t own, you had one tool: the extension method. Example:
public static class StringExtensions
{
public static bool IsLong(this string value)
=> value.Length > 50;
}
Nice and familiar. You call it as:
This works, but:
- You cannot add properties
- You cannot add static members
- You cannot group extensions by receiver type
- You must repeat the receiver type for every method
The concept was powerful, but not flexible.
What’s new in C# 14?
C# 14 introduces a new syntax:
extension(TypeName receiver)
{
// extension members go here
}
Inside this block, you can define:
- Instance extension properties
- Instance extension methods
- Static extension properties
- Static extension methods
This means you can now give external types a much more complete “virtual surface” of functionality — without modifying the original code, and without inheriting from it.
A Completely Original, Real-World Example
A common scenario in modern applications is working with sensor readings, telemetry, or IoT data.
Let’s build an example around a minimal domain type: TemperatureReading
Domain type:
public sealed class TemperatureReading(double value, DateTime timestamp)
{
public double Value { get; } = value;
public DateTime Timestamp { get; } = timestamp;
}
Now let’s extend it with C# 14’s new extension syntax.
Extension members:
public static class TemperatureReadingExtensions
{
// Instance extension members
extension(TemperatureReading r)
{
// Converts Celsius to Fahrenheit
public double Fahrenheit => (r.Value * 9d / 5d) + 32d;
// Checks whether the value exceeds a threshold
public bool IsCritical(double threshold = 35)
=> r.Value >= threshold;
// Human-friendly representation
public string ToLabel()
=> $"{r.Value:0.0} °C at {r.Timestamp:HH:mm:ss}";
}
// Static extension members
extension(TemperatureReading)
{
// Create a reading from °F inputs
public static TemperatureReading FromFahrenheit(double f, DateTime timestamp)
=> new((f - 32d) * 5d / 9d, timestamp);
// Neutral reading used for testing or diagnostics
public static TemperatureReading Neutral
=> new(0, DateTime.UnixEpoch);
}
}
Usage:
var reading = new TemperatureReading(29.4, DateTime.UtcNow);
double f = reading.Fahrenheit; // instance property
bool alert = reading.IsCritical(30); // instance method
string label = reading.ToLabel(); // method with formatting
var converted = TemperatureReading.FromFahrenheit(100, DateTime.UtcNow); // static extension
var baseline = TemperatureReading.Neutral; // static property
Why Extension Members Matter
1. More expressive APIs
1. More expressive APIs
Some behaviors are better expressed as properties than methods:
IsEmptyIsCriticalIsValidIsExpired
Before C# 14, extension properties were impossible.
2. Better type modeling without modifying the original code
A domain model from another team or library can now be extended elegantly:
- Add formatting helpers
- Add calculations
- Add computed values
- Add static factories
All without modifying the original type.
3. Cleaner grouping of extensions
Instead of repeating:
public static class XExtensions
{
public static ...
public static ...
public static ...
}
You can logically group by receiver type:
extension(MyType)
{
...
}
This keeps your extension library readable and maintainable.
Conclusion
Extension members in C# 14 greatly expand what developers can do without touching the underlying types. Properties, static members, and a cleaner syntax open the door to more expressive, discoverable, and maintainable APIs.
This feature will be particularly appreciated by:
- Library authors
- Domain-driven design practitioners
- Teams that work with immutable or external models
- Anyone building clean, expressive codebases
C# 14 is a small but meaningful step forward — and extension members are one of the features that will quietly improve day-to-day development for many of us.