File Scoped Namespaces and Global Usings

Dotnet 6 and Visual Studio 2022 are released and ready for production. This means that the new C# 10 is available.

Two of the most important features of the new C# are file scoped namespaces and global usings. These two features were introduced to save more space in the source code and help programmers write less code.

File Scoped Namespace

The file scoped namespace has developed because almost all source files contain only one namespace.

With C# 10 you can specify the namespace at the top. You do not need to ident your code or use curly braces.

Before:

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace EmagShop.Data // the namespace includes ident and braces 
{
    public class ApplicationDbContext : IdentityDbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
    }
}

After using file-scoped namespace:

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace EmagShop.Data;
public class ApplicationDbContext : IdentityDbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
}

If you use a file-scoped namespace you don’t need to use curly braces or to ident your code. The file looks much cleaner and you can see more code without having to scroll.

How to apply file-scoped namespace across all files

  1. Create a .editorconfig file with the following content:
    [*.cs]
    csharp_style_namespace_declarations = file_scoped:warning
  2.  Go to a file that has a normal namespace and press the bulb for quick actions: File-Scoped Namespace
  3. Select the option Solution in order to apply this change to the whole solution. file-scoped namespace for whole solution

 

Global Usings

A typical C# file contains four default namespaces:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; 
// other namespaces

These are included because many implementations use classes from these namespaces.

The idea of global usings is to remove the default namespaces from the source files and move them to the Csproj file.

How can I enable global using statements?

It is simple to enable global using statements.

  1. The application must use .NET 6 and C# 10.
  2. Edit the PropertyGroup tag in your  csproj file and add the following option:
    <PropertyGroup>
      <TargetFramework>net6.0</TargetFramework>
      <ImplicitUsings>enable</ImplicitUsings> <!--This is required-->  
     ...
    </PropertyGroup>

     

  3. You can specify a global using in two ways:
      • Specify in a source code file the global. You can create a file named GlobalUsings.cs and add the global using statements:
        global using BeautifyCode.Repos; //specify global keyword before a library
        using BeautifyCode.Repos.Signatures;
        using Microsoft.AspNetCore.Mvc;
      • Edit the csproj file and include an ItemGroup tag with the desired global usings. I personally prefer this method.
        <ItemGroup>
               <Using Include="Microsoft.AspNetCore.Mvc"/>
        </ItemGroup>

         

  4. By default DotNet 6 projects include some global usings. You can see them by searching in the obj folder for a file named with this pattern {SolutionName}.GlobalUsings.g.csHere are the default usings that I have found in this file:
    // <auto-generated/>
    global using global::Microsoft.AspNetCore.Builder;
    global using global::Microsoft.AspNetCore.Hosting;
    global using global::Microsoft.AspNetCore.Http;
    global using global::Microsoft.AspNetCore.Routing;
    global using global::Microsoft.Extensions.Configuration;
    global using global::Microsoft.Extensions.DependencyInjection;
    global using global::Microsoft.Extensions.Hosting;
    global using global::Microsoft.Extensions.Logging;
    global using global::System;
    global using global::System.Collections.Generic;
    global using global::System.IO;
    global using global::System.Linq;
    global using global::System.Net.Http;
    global using global::System.Net.Http.Json;
    global using global::System.Threading;
    global using global::System.Threading.Tasks;
    

    You can not use some of these namespaces by using the remove attribute of the using tag in the csproj file:

    <ItemGroup>
        <Using Remove="System"/>
        <Using Remove="System.IO"/>
        <Using Remove="System.Linq"/>
    </ItemGroup>

Source codes are cleaner in .NET 6

Look at the TextService class that I use in a .NET 5 project:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BeautifyCode.Services
{
    public class TextService : ITextService
    {
        public string HexToString(string hex)
        {
            hex = hex.Replace("-", "");
            byte[] raw = new byte[hex.Length / 2];
            for (int i = 0; i < raw.Length; i++)
            {
                raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
            }
            return Encoding.Default.GetString(raw);

        }
    }
}

In .NET 6, the class file becomes smaller due to the new features such as file-scoped namespaces and global usings:

using BeautifyCode.Services;

namespace BeautifyCode.Services;

public class TextRepo : ITextRepo
{
    public string HexToString(string hex)
    {
        hex = hex.Replace("-", "");
        byte[] raw = new byte[hex.Length / 2];
        for (int i = 0; i < raw.Length; i++)
        {
            raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
        }
        return Encoding.Default.GetString(raw);

    }
}

 

1 thought on “File Scoped Namespaces and Global Usings”

Leave a Comment