What's New In .NET 7?

Milan Jovanović - Sep 10 '23 - - Dev Community

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:

  • Required members
  • Generic attributes
  • Static abstract members in interfaces
  • file keyword
  • LINQ Order and OrderDescending

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; }
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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; }
}
Enter fullscreen mode Exit fullscreen mode

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

[TypedAttribute(typeof(int))]
public int Method() => default;
Enter fullscreen mode Exit fullscreen mode

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

public class TypedAttribute<T> : Attribute { ... }
Enter fullscreen mode Exit fullscreen mode

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

[TypedAttribute<int>()]
public int Method() => default;
Enter fullscreen mode Exit fullscreen mode

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; }
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

If you want to learn more, check out the docs onstatic abstract interface methodsand 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
{
}
Enter fullscreen mode Exit fullscreen mode

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 anIEnumerable, 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();
Enter fullscreen mode Exit fullscreen mode

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.


P.S. Whenever you're ready, there are 2 ways I can help you:

  1. 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 950+ students here.

  2. Patreon Community: Think like a senior software engineer with access to the source code I use in my YouTube videos and exclusive discounts for my courses. Join 820+ engineers here.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .