What's New In .NET 7?

What's New In .NET 7?

4 min read ·

Thank you to our sponsors who keep this newsletter free to the reader:

Wish you could calculate prices of your 2.68MM online products 3,000X faster without a batch job? By ditching their 12-JOIN SQL incantations, the “Amazon of medical supplies” went from pricing items in 3,000 milliseconds to 1 millisecond - all from within the database. Learn how RavenDB revolutionized the world's largest online medical supply store.

In this week's newsletter I want to highlight a few interesting things that are now available with the release of C# 11 and .NET 7.

In case you missed it, .NET 7 was released November 8th.

There are many new features, and you can be sure I had a hard time choosing which ones to highlight.

Here's what we are going to cover:

Let's see what the new features look like!

Required Members

We can now define a class member as required by using the required keyword. It can be applied to a field or property and it tells the compiler these members must be initialized by all constructors or by the object initializer.

Why is this useful?

Before C# 11, the only way to enforce a property being set was through a constructor. If you used an object initializer you could bypass the constructor and not initialize some properties.

Here's how you can say that a property is required:

public class ContentCreator
{
    public required string Firstname { get; init; }
    public string? MiddleName { get; init; }
    public required string LastName { get; init; }
}

If you try to create a new ContentCreator instance without initializing the required properties you get a compile error:

var creator = new ContentCreator
{
    FirstName = "Milan" // Error: No LastName
}

Generic Attributes

You can now declare a generic class whose base class is Attribute.

Before C# 11, if you wanted to pass in a type as a parameter to an Attribute you would need to pass it through the constructor:

public class TypedAttribute : Attribute
{
    public TypedAttribute(Type t) => Param = t;

    public Type Param { get; }
}

And here's how you would use it with the typeof operator:

[TypedAttribute(typeof(int))]
public int Method() => default;

Using the generic attributes feature, you can now define it like this:

public class TypedAttribute<T> : Attribute { ... }

Now, we can specify the type parameter as a generic argument:

[TypedAttribute<int>()]
public int Method() => default;

Static Abstract Members in Interfaces

This is a very interesting feature that allows abstracting of static operations. An example of this would be operators.

public interface IMonoid<TSelf> where TSelf : IMonoid<TSelf>
{
    public static abstract TSelf operator +(TSelf a, TSelf b);

    public static abstract TSelf Zero { get; }
}

How can we use the IMonoid interface?

It may be confusing at first, since the members are virtual and there is no instance to call the virtual members on. The solution is to use generics and let the compiler infer the rest.

Here's a simple example:

T AddAll<T>(params T[] elements) where T : IMonoid<T>
{
    T result = T.Zero;

    foreach (var element in elements)
    {
         result += element;
    }

    return result;
}

If you want to learn more, check out the docs on static abstract interface methods and generic math.

File Keyword

With the new file keyword you can define a type whose scope and visibility is restricted to the file in which it is declared.

file class HiddenClass
{
}

This feature is practical when used inside of source generators, to avoid collisions when naming generated types.

But you may be able to find a use for it in your application.

LINQ Order and OrderDescending

The new Order and OrderDescending methods allow us to sort an IEnumerable, which simplifies the code for sorting.

Here's an example of ordering an array:

var array = new[] { 19, 91, 21 };

var arrayAsc = array.Order();

var arrayDesc = array.OrderDescending();

I want to highlight that IQueryable also supports the new methods.

Will You Upgrade to .NET 7?

.NET 7 is not an LTS (Long Term Support) release, and will be in support until May 2024, with .NET 8 releasing in November 2023.

Here are a few reasons why you should consider upgrading:

  • Major performance improvements
  • New features in .NET 7
  • New features in EF Core 7
  • Easier migration to .NET 8

I will be moving some of my new projects from .NET 6 to .NET 7.

And I will also upgrade all of my YouTube content to .NET 7.


Whenever you're ready, there are 4 ways I can help you:

  1. Modular Monolith Architecture (COMING SOON): This in-depth course will transform the way you build monolith systems. You will learn the best practices for applying the Modular Monolith architecture in a real-world scenario. Join the waitlist here.
  2. Pragmatic Clean Architecture: This comprehensive course will teach you the system I use to ship production-ready applications using Clean Architecture. Learn how to apply the best practices of modern software architecture. Join 2,600+ students here.
  3. Patreon Community: Join a community of 1,050+ engineers and gain access to the source code I use in my YouTube videos, early access to future videos, and exclusive discounts for my courses. Join 1,050+ engineers here.
  4. Promote yourself to 47,000+ subscribers by sponsoring this newsletter.

Become a Better .NET Software Engineer

Join 47,000+ engineers who are improving their skills every Saturday morning.