# What's New In .NET 7?

> 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.

Published: 2022-11-12. Author: Milan Jovanović.

Canonical: https://milanjovanovic.tech/blog/whats-new-in-dotnet-7

**.NET 7** was released on November 8th, 2022, alongside **C# 11**.
The language highlights are `required` members, generic attributes, static abstract members in interfaces, and the `file` keyword.
On the library side, LINQ added the `Order` and `OrderDescending` methods, which sort an `IEnumerable` without a key selector.

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](#required-members)
- [Generic attributes](#generic-attributes)
- [Static abstract members in interfaces](#static-abstract-members-in-interfaces)
- [`file` keyword](#file-keyword)
- [LINQ Order and OrderDescending](#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:

```csharp
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:

```csharp
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:

```csharp
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:

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

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

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

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

```csharp
[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.

```csharp
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:

```csharp
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](https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/interface-implementation/static-virtual-interface-members#static-abstract-interface-methods)
and [generic math](https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/interface-implementation/static-virtual-interface-members#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.

```csharp
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:

```csharp
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**.

---

## Frequently asked questions

### What is the required keyword in C# 11?

C# 11 added the required modifier for fields and properties. It tells the compiler those members must be initialized by every constructor or by the object initializer, so leaving one out produces a compile error instead of a silently unset property.

### What are generic attributes in C#?

C# 11 let you declare a generic class whose base class is Attribute. Instead of passing a Type through the attribute constructor with typeof, you supply the type as a generic argument directly on the attribute.

### What are static abstract members in interfaces?

.NET 7 introduced static abstract interface members, which let interfaces abstract static operations such as operators. You consume them through generics and let the compiler resolve the static member for the concrete type. This feature underpins generic math.

### What is the file keyword in C#?

C# 11 added the file keyword, which restricts a type's scope and visibility to the file in which it is declared. It is mainly practical inside source generators, to avoid naming collisions between generated types.

### What do the LINQ Order and OrderDescending methods do?

.NET 7 added Order and OrderDescending, which sort an IEnumerable by the elements themselves without a key selector, simplifying sorting code. IQueryable supported the new methods as well.

### Was .NET 7 a long-term support (LTS) release?

No. .NET 7 was a standard-term support release, supported until May 2024, with .NET 8 releasing in November 2023. Upgrading still brought major performance improvements, new EF Core 7 features, and an easier migration path to .NET 8.
