In this article, we are going to learn about Global Using Directives in C#.

When we create a console application using .NET 6, the Program.cs class contains a single line of code (not counting the comment):

// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");

This application is very minimal compared to previous .NET versions. Global Using Directive powers this clean code, and in this article, we will learn more about it.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!
To download the source code for this article, you can visit our GitHub repository.

Let’s dive in.

How Do We Use Global Using Directives?

Before C# 10, we had to import namespaces as we needed them. So if our entire application needs a given namespace, we have to import it into every file. With global using directives, we can declare namespaces once and they become available to all files in the application. 

Declaring Global Using Directives

We declare global usings by using two ways. In a first way, we define the global using directive in any file within our project. Another way is declaring our global usings in the main Project file(.csproj). We will discuss this later when we talk about implicit global using directives. Let’s inspect the first way.

Back to our console application, let’s add a Store class:

namespace GlobalUsingDirectiveInCSharp.Model
{
    public class Store
    {
        public string? Name { get; set; }

        public string? Owner { get; set; }
    }
}

Furthermore, let’s make use of the Store class:

using GlobalUsingDirectiveInCSharp.Model;

var store = new Store { Name = "Fred and Sons Bakery", Owner = "Fred" };

Console.WriteLine($"{store.Name} is owned by {store.Owner}");

For every file that we use Store, we have to declare its namespace – using GlobalUsingDirectiveInCSharp.Model. 

On the other hand, to make Store accessible globally, we add the global keyword before the using statement:

global using GlobalUsingDirectiveInCSharp.Model;

With global keyword added we can access Store from any file within our console application. Also, when we declare a global using directive and a non-global using directive in the same file, the global using directive must be declared first before the non-global directive.

We would get the error if we don’t follow the rule:

A global using directive must precede all non-global using directive

We can define global using directives in any file. However, it is recommended to place all global usings in a single file. This makes it easier for us to maintain them in larger applications. 

Implicit Global Using Directives

Another feature used in making our console application minimal is the Implicit Global Using Directives. The .NET SDK automatically generates global using directives called implicit global using directives. This is a new feature in .NET 6: 

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

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

This is the .csproj file of our console application. To use implicit global using directives, the setting <ImplicitUsings> is set to enable. <implicitUsings> are enabled by default when creating new applications.

Now, let’s see where we can find the implicit global using directives that are defined in our application:

obj\Debug\net6.0\GlobalUsingDirectiveInCSharp.GlobalUsings.g.cs

Implicit global usings differ between projects.

Let’s inspect the global usings file for the Console application:

// <auto-generated/>
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.Threading;
global using global::System.Threading.Tasks;

 Additionally, let’s inspect the same for a Web API project:

// <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;

We can also remove any implicit global using directive we don’t need it.

Let’s see how:

<ItemGroup>
    <Using Remove="System.Collections.Generic"></Using>
</ItemGroup>

When we add this tag in .csproj, we remove the implicit global using directive of System.Collections.Generic. On running our application, the namespace is removed from the GlobalUsings.g.cs file.

To enable a directive, we use Include tag within <Using> settings:

<ItemGroup>
  <Using Remove="System.Collections.Generic"></Using>
  <Using Include="GlobalUsingDirectiveInCSharp.Model"></Using>
</ItemGroup>

With this in place, we can remove the global using directive we define for the Store class in any file and the application will still run.

Disabling Implicit Global Using Directives

We can disable Implicit Global Using Directives by setting <implictUsings> in our .cproj file to disable:

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

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>disable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <Using Remove="System.Collections.Generic"></Using>
    <Using Include="GlobalUsingDirectiveInCSharp.Model"></Using>
  </ItemGroup>

</Project>

Just a single note here. Even though we disable implicit using directives inside the PropertyGroup, we will still be able to access those namespaces included inside the ItemGroup part. This setup will override the <ImplicitUsings> one. So basically, if we want we can disable all the global usings, and then enable just the required ones.

Conclusion

In this article, we have learned about Global Using Directives and how to declare one. We also covered Implicit Global Using Directives. Both features make for a cleaner code in the latest C# 10 and .NET 6.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!