Hi all. Been a while since I’ve done one of these. Thanks for continuing to subscribe! And if you’d like this post in cringe Youtube video form, check out:
1. Null-Conditional Assignment (?=)
We've all written this boilerplate code a thousand times. You have a nullable object, and you only want to assign a value to one of its properties if the object itself isn't null.
In C# 13, you had to perform an explicit null check.
public class Channel
{
public int Subscribers { get; set; }
public int Members { get; set; }
}
// ---
Channel? myChannel = null; // or new Channel();
// We have to check for null before assigning
if (myChannel is not null)
{
myChannel.Subscribers = 1000;
}
After: C# 14
With the new null-conditional assignment operator (?=), you can do this in a single, safe, and readable line.
Channel? myChannel = null;
// This will only assign 1000 if myChannel is not null
myChannel?.Subscribers = 1000;
It's a small change, but a very welcome one!
2. The field Keyword for Semi-Auto-Properties
Auto-properties are great, but as soon as you need to add logic to your getter or setter (like validation), you have to convert it to a full property with an explicit private backing field.
Before: C# 13
This required creating a separate field (_subscribers) just to add a check in the setter.
public class Channel
{
private int _subscribers;
public int Subscribers
{
get => _subscribers;
set
{
if (value < 1000)
{
throw new ArgumentException("Not enough subs!");
}
_subscribers = value;
}
}
}
After: C# 14
The new field keyword gives you access to the implicit, compiler-generated backing field of an auto-property. This means you can add logic without the boilerplate!
public class Channel
{
public int Subscribers
{
get => field; // 'field' refers to the implicit backing field
set
{
if (value < 1000)
{
throw new ArgumentException("Not enough subs!");
}
field = value; // Assign to the implicit backing field
}
}
}
This keeps the code much cleaner and more concise.
3. User-Defined Compound Operators
This one is really cool. Have you ever wanted to define what a compound operator like ++ or += does for your own custom type? Now you can!
Imagine we want the ++ operator to increment both the Subscribers and Members properties of our Channel class at the same time.
Before: C# 13
You'd have to increment each property manually.
var myChannel = new Channel();
myChannel.Subscribers++;
myChannel.Members++;
After: C# 14
You can now overload the compound operator directly in your class definition.
public class Channel
{
public int Subscribers { get; set; }
public int Members { get; set; }
public void operator ++()
{
Subscribers++;
Members++;
}
public void operator +=(int amount)
{
Subscribers += amount;
Members += amount;
}
}
// ---
var myChannel = new Channel();
myChannel++; // This now increments both Subscribers and Members!
Console.WriteLine($"Subs: {myChannel.Subscribers}, Members: {myChannel.Members}");
// Output: Subs: 1, Members: 1
Not sure where I’d use this but hey ho!
4. The extension Keyword
Extension methods have always required a public static class and public static methods using the this keyword. C# 14 introduces a new, more explicit syntax.
Before: C# 13
The classic syntax we all know.
public static class ChannelExtensions
{
public static void PrintDetails(this Channel c)
{
Console.WriteLine($"Subs: {c.Subscribers}, Members: {c.Members}");
}
}
After: C# 14
You can now use the extension keyword to create an "extension type." The syntax is cleaner and makes the intent clearer.
public extension ChannelExtensions
{
public void PrintDetails(this Channel c)
{
Console.WriteLine($"Subs: {c.Subscribers}, Members: {c.Members}");
}
}
Personally, I'm not totally sold on this one yet, as it just creates another way to do the same thing. You can now use extension methods to add Properties, but still…
5. nameof Improvements for Generics
The nameof operator is a handy tool for getting the string name of a variable, type, or member. However, it had a limitation with generic types.
Before: C# 13
nameof worked on a constructed generic type, but not on an "unbound" or open generic type.
C#
public class Channel<T> { }
public class YouTube { }
// This worked fine
Console.WriteLine(nameof(Channel<YouTube>)); // Output: Channel
// This caused a compile error
// Console.WriteLine(nameof(Channel<>));
After: C# 14
This limitation has been removed. You can now use nameof directly on an unbound generic type.
C#
// Now this works perfectly!
Console.WriteLine(nameof(Channel<>)); // Output: Channel
This is a nice little fix for those edge cases where you need the name of the generic type definition itself.
My thoughts on C# 14
Actually they’ve been quite restrained this year. No crazy new ways to instantiate lists or classes that conceptually forks C#. I do get alot of comments on my channel saying that C# is getting too complicated, so glad they have shown restraint. Well done chaps!

