DEV Community

Cover image for .NET 7 is on the way! 5 Features that will blow your mind 🤯
ByteHide
ByteHide

Posted on • Edited on • Originally published at bytehide.com

.NET 7 is on the way! 5 Features that will blow your mind 🤯

It’s no secret that Microsoft has been working on .NET 7 for quite some time now, and every time someone asks about it, the company has stated that it’s still in development and that we’ll get more information when the time is right.

Well, guess what? The time is right! Recently, Microsoft announced that .NET 7 will be officially released in November this year and revealed many of its new features. Needless to say, they’re pretty exciting! Let’s take a look at why so many people are excited about the future of .NET 7.


Critical Performance Tags

Microsoft tells us that it is now possible to expose tag enumerator methods. This is especially intended for critical scenarios where performance is of vital importance and can now be achieved using ActivityEvent and ActivityLink.

This is an example of use that Microsoft gives us:

var tags = new List<KeyValuePair<string, object?>>()
{
    new KeyValuePair<string, object?>("tag1", "value1"),
    new KeyValuePair<string, object?>("tag2", "value2"),
};

ActivityLink link = new ActivityLink(default, new ActivityTagsCollection(tags));

foreach (ref readonly KeyValuePair<string, object?> tag in link.EnumerateTagObjects())
{
    // Consume the link tags without any extra allocations or value copying.
}            

ActivityEvent e = new ActivityEvent("SomeEvent", tags: new ActivityTagsCollection(tags));

foreach (ref readonly KeyValuePair<string, object?> tag in e.EnumerateTagObjects())
{
    // Consume the event's tags without any extra allocations or value copying.
}
Enter fullscreen mode Exit fullscreen mode

In this way, object enumerations can be performed with no loss of speed or performance and with easy and fast access to the elements.

Moreover, Mikel Blanchard — the author of this proposal, adds a t*est comparing 3 scenarios* in which he clearly shows that this new feature increases performance exponentially and in turn reduces error time.

First of all Mikel explains that enumerating is much more demanding to enumerate using that API than using Enumerate* API:

public IEnumerable<KeyValuePair<string, object?>>? Tags { get; }
Enter fullscreen mode Exit fullscreen mode

And the results were as follows:

Image description

In the next test, Mikel improved performance by 71% (although he considered it “also very slow).

In this case it was performed with:

foreach (KeyValuePair<string, object> tag in (ActivityTagsCollection)activityEvents.Tags
Enter fullscreen mode Exit fullscreen mode

And this was reflected in a 71% improvement in performance:

Image description

After that, he decided to perform the same test but enumerating over an array:

        private struct Enumerator
        {
            private readonly KeyValuePair<string, object>[] source;
            private int index;

            public Enumerator(KeyValuePair<string, object>[] source)
            {
                this.source = source;
                this.index = -1;
            }

            public readonly KeyValuePair<string, object> Current => this.source[this.index];

            public readonly Enumerator GetEnumerator() => this;

            public bool MoveNext()
            {
                return ++this.index < this.source.Length;
            }
        }
Enter fullscreen mode Exit fullscreen mode

And the result was 83% more performance compared to the previous test performed by Mikel:

Image description

📚 Note: If you wish to consult more information about the tests, I recommend you take a look at the original proposal: API Proposal: #68056


System.Text.Json improvements

In previous versions this was not possible but thanks to these additions to System.Text.Json , serialization and deserialization of polymorphic type hierarchies is now possible.

Let’s look at the Microsoft example:

[JsonDerivedType(typeof(Derived))]
public class Base
{
    public int X { get; set; }
}

public class Derived : Base
{
    public int Y { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Serialization:

Base value = new Derived();
JsonSerializer.Serialize<Base>(value); // { "X" : 0, "Y" : 0 }
Enter fullscreen mode Exit fullscreen mode

Deserialization:

Base value = JsonSerializer.Deserialize<Base>(@"{ ""X"" : 0, ""Y"" : 0 }");
value is Derived; // false
Enter fullscreen mode Exit fullscreen mode

In this case Eirik Tsarpalis states in his proposal that a type discriminator must be specified to enable polymorphic deserialization. This is the way he shows it:

[JsonDerivedType(typeof(Base), typeDiscriminator: "base")]
[JsonDerivedType(typeof(Derived), typeDiscriminator: "derived")]
public class Base
{
    public int X { get; set; }
}

public class Derived : Base
{
    public int Y { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

📚 Note: If you wish to consult more information about the serialization and deserialization, I recommend you take a look at the original proposal: Dotnet Issue: #63747


CopyString UTF-8 & UTF-16

New methods are now included to be able to consume decoded JSON strings. Previously this was only possible using Utf8JsonReader.GetString() but now with CopyString you can copy UTF-8 strings or even UTF-16 strings without decoding.

Microsoft leaves this example:

int valueLength = reader.HasReadOnlySequence ? checked((int)ValueSequence.Length) : ValueSpan.Length;
char[] buffer = ArrayPool<char>.Shared.Rent(valueLength);
int charsRead = reader.CopyString(buffer);
ReadOnlySpan<char> source = buffer.Slice(0, charsRead);

ParseUnescapedString(source); // handle the unescaped JSON string
ArrayPool<char>.Shared.Return(buffer);
Enter fullscreen mode Exit fullscreen mode

📚 Check original source: Dotnet Issue: #54410


Analyzer

We now have a new analyzer. This analyzer is in charge of looking for the Regex uses with the possibility of conversion for the use of the RegexGenerator source generator:

Image description

According to Microsoft, the generator output depends on the known values of the parameters supplied:

“They are part of an app that targets .NET 7. The new analyzer ships inside the .NET 7 targeting pack and only apps targeting .NET 7 are eligible for this analyzer.

The LangVersion is higher than 10. For the time being the regex source generator requires LangVersion to be set to preview.”

📚 Check original source: Analyzer


Code fixer

Of course, if you have an Analyzer, you can’t miss a Code Fixer. Well, here it is, Microsoft tells us that the first of its two functions (for the moment, let’s keep waiting for more news) is in charge of suggesting RegexGenerator source generator methods with the possibility of overriding the name that comes by default

The second function of this code fixer that comes in .NET 7 is that, through a call to the new method, it replaces the original code.

Let’s see how the code fixer looks like in the Microsoft example:

Image description

📚 Check original source: Code Fixer

There are still a couple of months to go until the official release of .NET 7 by Microsoft but all the previews that have already been released (along with this latest one), have seemed to me to be very good and with a pretty big performance focus. We can only wait to see what Microsoft is up next.


If you want to be the first to know about all the latest .NET and C# news, follow us so you won’t miss a thing!

Top comments (2)

Collapse
 
kaylumah profile image
Max Hamulyák

From these changes I am most exited about the analyzers / source generators that is powerfull stuff :)

Collapse
 
olivierspinelli profile image
Olivier Spinelli

It sems you totally misunderstood the first point: this is just a minor perf. fix to a (rarely used) API using basic stuff. You should remove it, this has nothing to do here.