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