
Are you excited about the new features in C# 13 and .NET 9? Microsoft has introduced some amazing updates to make coding easier, faster, and more efficient. Whether you’re just starting out or already coding in .NET, this article will break down the top 10 features in simple terms so you can start using them right away.
1. Simplified Locking with System.Threading.Lock
C# 13 replaces the old way of locking with objects by introducing the new Lock
type. It makes your code easier to read and improves performance.
Old Way:
public class LockExample
{
private readonly object _lock = new();
public void DoStuff()
{
lock (_lock)
{
Console.WriteLine("Inside old lock");
}
}
}
New Way:
public class LockExample
{
private readonly Lock _lock = new();
public void DoStuff()
{
lock (_lock)
{
Console.WriteLine("Inside .NET 9 lock");
}
}
}
Why This Matters:
- Easier to understand and use.
- Safer for beginners to avoid mistakes.
- Works faster under the hood.
Pro Tip: If you need async locking, use SemaphoreSlim
:
private readonly SemaphoreSlim _semaphore = new(1, 1);
public async Task DoStuffAsync()
{
await _semaphore.WaitAsync();
try
{
await Task.Delay(1000);
}
finally
{
_semaphore.Release();
}
}
2. Task.WhenEach
for Managing Tasks
Handling multiple tasks just got easier. C# 13 introduces Task.WhenEach
, letting you process tasks as they complete.
Old Way:
while (tasks.Count > 0)
{
var completedTask = await Task.WhenAny(tasks);
tasks.Remove(completedTask);
Console.WriteLine(await completedTask);
}
New Way:
await foreach (var completedTask in Task.WhenEach(tasks))
{
Console.WriteLine(await completedTask);
}
Why This Matters:
- Cleaner and shorter code.
- Perfect for beginners managing task-based programs.
3. params
Collections Made Flexible
C# 13 now supports collections like IEnumerable
for params
, making your functions more versatile.
Old Way:
static void WriteNumbers(params int[] numbers)
{
Console.WriteLine(numbers.Length);
}
New Way:
static void WriteNumbers(params IEnumerable<int> numbers)
{
Console.WriteLine(numbers.Count());
}
Why This Matters:
- No need to convert collections into arrays.
- Saves time and memory.
4. Semi-Auto Properties with field
Stop writing boilerplate code for properties! C# 13 introduces the field
keyword for direct access to backing fields.
Old Way:
public class Example
{
private int _number;
public int Number
{
get => _number * 10;
set
{
if (value < 0) throw new ArgumentOutOfRangeException();
_number = value;
}
}
}
New Way:
public class Example
{
public int Number
{
get => field * 10;
set
{
if (value < 0) throw new ArgumentOutOfRangeException();
field = value;
}
}
}
Why This Matters:
- Code is simpler and cleaner.
- Focus on logic, not repetitive tasks.
5. Hybrid Cache for Flexible Storage
Meet the new HybridCache
API! It combines in-memory and distributed caching for better performance and flexibility.
Example:
var posts = await hybridCache.GetOrCreateAsync(cacheKey,
async _ => await GetPostsAsync(userId),
new HybridCacheEntryOptions
{
Flags = HybridCacheEntryFlags.DisableLocalCache |
HybridCacheEntryFlags.DisableDistributedCache
});
Why This Matters:
- Combines local (fast) and distributed (shared) caching.
- Easy to use for large-scale apps.
6. Built-in OpenAPI for APIs
.NET 9 now generates OpenAPI documentation automatically, no extra libraries needed!
Old Way:
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
New Way:
builder.Services.AddOpenApi();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
Why This Matters:
- Saves setup time for beginners.
- Works out of the box for API documentation.
7. String Search Made Easy with SearchValues
The updated SearchValues
API supports strings and custom comparison types, making text processing simpler.
Example:
var keywordSearch = SearchValues.Create(["new", "of"], StringComparison.OrdinalIgnoreCase);
Console.WriteLine(text.ContainsAny(keywordSearch));
Why This Matters:
- Faster and more powerful string searches.
- Great for filtering or validating user input.
8. New LINQ Methods for Everyday Tasks
.NET 9 introduces these handy LINQ methods:
CountBy
: Counts items by a key.AggregateBy
: Groups and summarizes data.Index
: Finds an item’s index.
Example:
var firstNameCounts = people.CountBy(p => p.firstName);
foreach (var entry in firstNameCounts)
{
Console.WriteLine($"First Name {entry.Key} appears {entry.Value} times");
}
Why This Matters:
- Write fewer loops.
- Handle data with minimal code.
9. using ref
for Memory Efficiency
The using ref
feature in C# 13 helps manage memory better, especially when working with structs.
Example:
ref var data = ref GetData();
using ref data
{
Console.WriteLine(data);
}
Why This Matters:
- Perfect for low-level, performance-critical scenarios.
- Ensures safe memory handling.
10. Native Ahead-of-Time (AOT) Compilation
.NET 9 takes performance to the next level with AOT compilation, creating lightweight, optimized apps.
Benefits:
- Faster startup times.
- Smaller app sizes.
- Perfect for microservices and cross-platform development.
11. Other Features
Below is a list of other interesting changes that are definitely worth your attention but are likely to be adopted less broadly and address more specific use cases.
- Implicit index access
- Partial properties
- Allows
ref struct
- Base64Url
- Collection lookups with spans
- Feature switches with trimming support
Regex.EnumerateSplits
- New capabilities of
System.Text.Json
OrderedDictionary<TKey, TValue>
ReadOnlySet<T>
Debug.Assert
now reports assert condition- New
Tensor<T>
Type
Final Thoughts
These new features make .NET 9 and C# 13 perfect for both beginners and seasoned developers. Whether you’re coding APIs, handling tasks, or optimizing performance, there’s something here for everyone.
Want to stay updated on the latest .NET features? Bookmark this page or share it with your friends who are starting their .NET journey!
Further Reading
To continue your learning journey, check out these related resources: