It's November already! After months of rumors, speculations, and so on, Microsoft will finally reveal .NET 6 at .NET Conf next week.
This release includes lots of new features as well as speed and efficiency enhancements.
Let's take a closer look at The 5 Most Important .NET 6 Features.
C# 10
Right now, C# 10 It is regarded by Microsoft as one of the most critical components of .NET 6. C# 10 is mostly an extension of what currently existing, both in terms of concepts and capabilities and features, registries, or patterns.
To summarize a little what brings C# 10, the global using
, the namespaces with file scope and more very good characteristics that will allow to simplify the code and to write less repetitions.
Record structs
Finally, registry structs are supported in the C# 10 version. To understand this new feature, compare it to the records in the C# 9 version (class-based), but with a few modifications.
The most significant change is the addition of registry structs for completeness, so that structs can enjoy the same registry benefits as classes.
But that’s not all, Microsoft did not only limit itself to struct records, but also, they decided to align class records as much as struct records with ValueTuple
.
The result of this?
Well, the struct properties of records are mutable by default, while the class properties of records are immutable. Although it is still possible to declare a readonly record struct
, which matches the semantics of the record class
and is immutable.
Record structures, to be clear, DO NOT REPLACE record classes. According to Microsoft, the conversion from record classes to record structures is not "encouraged" . This class use recommendation applies equally to registry structs as it does to registry classes.
In Microsoft’s own words:
“…In other words, the choice between classes and structs must be made before choosing to use registers…”
Record structs in action
What better way to explain the theory than to look at a real example? Let's get started:
Battery battery = new("CR2032", 0.235, 100);
WriteLine(battery);
while (battery.RemainingCapacityPercentage > 0)
{
battery.RemainingCapacityPercentage--;
}
WriteLine(battery);
public record struct Battery(string Model, double TotalCapacityAmpHours, int RemainingCapacityPercentage);
And that's what the code would yield if it were run:
Battery { Model = CR2032, TotalCapacityAmpHours = 0.235, RemainingCapacityPercentage = 100 }
Battery { Model = CR2032, TotalCapacityAmpHours = 0.235, RemainingCapacityPercentage = 0 }
You'll see that it's quite close to the record example in C# 9:
Battery battery = new("CR2032", 0.235, 100);
WriteLine(battery);
while (battery.RemainingCapacityPercentage > 0)
{
Battery updatedBattery = battery with
{RemainingCapacityPercentage =
battery.RemainingCapacityPercentage - 1};
battery = updatedBattery;
}
WriteLine(battery);
public readonly record struct Battery(string Model, double TotalCapacityAmpHours, int RemainingCapacityPercentage);
To reiterate, the key differentiating characteristic of record struct properties (apart from the record struct syntax) is that they are modifiable.
What are the main differences between struct records and class records?
Record classes are defined with
record
orrecord class
.The properties of the
record class
are immutable (get/init) by default.Record struct properties are mutable (get/set) by default.
Records are defined with record
struct
orreadonly record struct
.
Why do Struct records look like Class records?
Support
with
expressions.They have the ability to customize member definitions (which is new in C# 10) to use fields instead of default property members.
The syntax used is the same (except
struct
orclass
in the definition).Allow to customize member behavior, using
init
or mutable properties.
Global usings
You can now use the global
modifier to any using directive. With this you can tell the compiler that the directive must be applied to all source files in the compilation.
Perfect, but, as already mentioned…
What is the using directive?
This directive allows you to use types defined in a namespace without specifying the entire namespace of that type.
To summarize, the using
directive imports all types from a single namespace, as shown in the following example:
using System.Text;
You can apply two modifiers to a using
directive:
The
global
modifier has the same effect as adding the sameusing
directive to every source file in your project. This modifier was introduced in C# 10.0.The
static
modifier imports thestatic
members and nested types from a single type rather than importing all the types in a namespace.
Let’s look at different types of syntaxes:
global using System;
global using static System.Console;
global using E = System.Environment;
File-scoped namespace declaration
You can now specify that all subsequent defined declarations are members of the declared namespace using the new namespace declaration form:
namespace NamespaceName;
Before it was like this:
namespace NamespaceName
{
}
The improved syntax, which will be included in C# 10, will save both vertical and horizontal space for the most popular namespace declarations.
Const
and interpolated strings
Strings that have been interpolated can now be assigned to const variables. These interpolated strings are simple to understand and apply. They should be usable in any situation. They can now be combined with const if the placeholder values are likewise const.
Let’s look at the Microsoft example:
const string Bar = "Bar";
const string DoubleBar = $"{Bar}_{Bar}";
WriteLine(DoubleBar);
Extended property patterns
You may now reference nested fields using a property pattern. This is the finest example (before) to comprehend it:
{ Prop1: { Prop2: pattern } }
And now it can be done perfectly well like this:
{ Prop1.Prop2: pattern }
You can see this more compact form used in the following example by Microsoft taken from RC 2 of .NET 6, for example with Reading.PM25
:
List<Status> statuses = new()
{
new(Category.Normal, new(20, false, 20)),
new(Category.Warning, new(20, false, 60)),
new(Category.Danger, new(20, true, 60)),
new(Category.Danger, new(100, false, 20))
};
foreach (Status status in statuses)
{
string message = status switch
{
{Category: Category.Normal} => "Let the good times roll",
{Category: Category.Warning, Reading.PM25: >50 and <100} =>
"Check the air filters",
{Reading.PM25: >200 } => "There must be a fire somewhere.
Don't go outside.",
{Reading.SmokeDetected: true } => "We have a fire!",
{Category: Category.Danger} => "Something is badly wrong",
_ => "Unknown status"
};
Console.WriteLine(message);
}
record struct Reading(int Temperature, bool SmokeDetected, int PM25);
record struct Status(Category Category, Reading Reading);
enum Category
{
Normal,
Warning,
Danger
}
✅ .NET 6 Conclusion
The features have been added of .NET 6 are numerous; however, the majority of them have yet to be fully utilized (despite the fact that this is the RC 2 Preview), and we will have to wait for Microsoft to discuss them in detail in the not-too-distant long term, as we are only a few days away from the official release the next week.
Microsoft says:
“It’s inspiring to see the new features in .NET 6 that will lay the foundation for what’s coming next. These are big-bet features that will push the platform forward in both obvious and non-obvious ways.”
If you liked this article, don’t forget to FOLLOW US, so that you can be one of the first to read what’s new in .NET.
Top comments (5)
Is anyone still using .net? I wonder which software it's still good for?
Hi Ivan 🙂
It really can be used for almost anything:
Just in this article we have talked about its uses in case you are interested.
Thanks for your time! 🤗
Thanks, but there's a difference between what it can be used for and what it IS used for. Do you have maybe links for successful projects in OSS that are using .NET?
Hi Ivan, I'm a full-stack dotnet developer and in the company I work for we use dotnet for most of the applications, specially web apps and desktop apps.
We are currently working on a warehouse management system and some systems to interact with ERPs
☕☕☕☕☕