.NET Tools How-To's

File-Scoped Namespaces – A Look at New Language Features in C# 10

ReSharper and Rider support for C# 8

Welcome to the first part of our series, where we take a closer look at the new C# language features the .NET team has implemented, and how ReSharper and Rider make it easy to adopt them in your codebase. Welcome to C# 10 and .NET 6!

In this series, we are looking at:

In this post we will talk about how to start using C# 10 in your projects and discuss file-scoped namespaces in depth. Have fun and be amazed!

How To Start Using C# 10

First of all, you will need the .NET 6.0 preview installed on your machine. Once installed, you can update the language version of your project. In Rider, we can do this from the Project Properties dialog:

Change Language Version from Project Dialog

Alternatively, you can hit Alt+Enter on any compiler error and execute the quick-fix:

Change Language Version via Quick-Fix

Or manually update your project file as follows:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net6.0</TargetFramework>
        <LangVersion>preview</LangVersion>
    </PropertyGroup>

</Project>

File-Scoped Namespaces

Most of you will probably confirm, that their C# files only contain a single namespace declaration:

namespace ConsoleApp
{
    class Utilitiy { }
    // other types
}

The new file-scoped namespaces allow you to declare them for the whole file and without using a block:

namespace ConsoleApp;

class Utility { }
// other types

This is truly a real-estate saver since you no longer have to apply a wasteful indentation to your whole type declarations in a file. If you’ve been using a custom Indent Size (usually 2 spaces) under Code Style | Tabs, Indents, Alignment or disabled the Indent inside namespace declaration setting under Code Style | Braces Layout, you can now come back to the language defaults.

ReSharper and Rider allow for a frictionless transition to file-scoped namespaces. From a single block-scoped namespace declaration, you can choose to switch styles for the file, project, or entire solution:

Convert to File-Scoped Namespaces in Solution

Remember: you can use git blame -w to ignore whitespace changes from bulk formatting commits. Rider uses the switch by default for its Git Annotate action.

In order to achieve consistency, there is a new code style setting under Code Editing | C# | Syntax Style | Code Body to choose your preference and the violation severity. This is useful, for instance, when you converted your main branch but want to merge a branch that still uses block-scoped namespaces.

Change Syntax Style for Namespaces

Remember: Code Styles are best saved to the team-shared settings layer.

If you have defined custom file templates, there is very good news: existing templates are file-scope ready. That means that ReSharper and Rider will convert the declaration automatically according to your code style settings. At the same time, when creating new templates with file-scoped namespaces, they are converted back to block-scoped when needed:

Existing File Template using Block-Scoped Namespaces

When we talk about file-scoped namespaces, some of you are probably reminded of package headers in Java and Kotlin. Unlike their counterpart, file-scoped namespaces in C# are not required to appear at the top of the file, meaning they are allowed to be preceded by using directives. We expect most developers to prefer them right before type declarations, but you can configure this with the existing Add ‘using’ directive to deepest scope setting under the Code Style | Syntax Style options:

Existing File Template using Block-Scoped Namespaces

Download ReSharper 2021.3 EAP or check out Rider 2021.3 EAP to start taking advantage of C# 10 in the best possible way. We’d love to hear your thoughts!

image description