NET 6 -  Global Using : Usando o modificador global na diretiva using


Hoje veremos o novo recurso Global Using que permite usar o modificador global com a diretiva using.

O novo recurso do C# 10 chamado de Global Using tem como objetivo simplificar e tornar o código C# mais leve declarando apenas uma vez a diretiva using em um namespace específico em um mesmo projeto.

Atualmente no início de um arquivo C# geralmente é feita a declaração dos recursos usados usando a diretiva using que especifica os namespaces que o código do arquivo vai precisar para compilar.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Dapper;
using AutoMapper;
...

Quando temos muitos arquivos no mesmo projeto, é provável que muitas das instruções using sejam repetidas em todos os arquivos e assim acabamos repetindo código.

O novo recurso Global Using do C# 10 introduz a palavra-chave global que podemos usar para identificar diretivas using que deverão ser aplicados a todos os arquivos da solução.

global using System;
global using System.Collections.Generic;
global using System.Threading.Tasks;
global using Dapper;
global using AutoMapper;
...

Essas instruções podem ser colocadas em um arquivo separado em algum lugar do projeto, e o compilador C # saberá que todos esses namespaces se aplicam a todos os arquivos do projeto.

Exemplo prático

Vamos criar um projeto do tipo Console no Visual Studio 2022 usando o NET 6 com o nome GlobalUsing.

A seguir vamos definir o código abaixo na classe Program:

Curso curso = await GetCurso();
Console.WriteLine($"Alunos do curso {curso.Nome}\n");
foreach (Aluno aluno in curso.Alunos)
{
    Console.WriteLine($" - {aluno.Nome}");
}
static async Task<Curso> GetCurso()
{
    Curso curso = new("C# 10", new List<Aluno> { new("Maria"), new("Pedro") });
    return await Task.FromResult(curso);
}
Console.ReadKey();
public record Aluno(string Nome);
public record Curso(string Nome, List<Aluno> Alunos);

Neste código estamos usando alguns recursos do C# 9 como :

Agora observe que aqui não estamos usando nenhum namespace neste arquivo mas teriamos que declarar os namespaces:

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

Podemos agora usar o recurso global using criando um arquivo chamado Usings.cs e incluindo neste arquivo o código abaixo:

Com isso não precisamos definir nenhum namespace na classe Program pois os namespaces definidos como global serão incluídos em todos os arquivos do projeto.

Executando o projeto veremos que ele funciona sem problema algum:

Agora vamos criar uma classe Teste com o código abaixo neste projeto:

namespace GlobalUsing
{
    public class Teste
    {
        private static async Task<string> ConcatenaAsync()
        {
            var palavra = string.Empty;
            //gera numeros inteiros de 65 a 91(A a Z) e concatena
            foreach (var contador in Enumerable.Range(65, 26))
            {
                palavra = string.Concat(palavra, (char)contador);
                await Task.Delay(150);
            }
            return palavra;
        }
    }
}

Aqui estou usando a sintaxe padrão do C#. Observe que nesta classe eu estou usando o namespace System.Linq.

Usando o recurso Global Using podemos agora mover este namespace para o arquivo Usings.cs :

Agora o namespace System.Linq será incluído no arquivo Teste e não precisamos declará-lo neste arquivo.

Se por caso eu esquecer e tentar declarar um namespace que já esta definido como global, o compilador vai sinalizar indicando que os namespaces são desnecessárias pois já foram declarados :

Então, a partir do .NET 6 RC 1, nenhuma diretiva de uso global implícita é adicionada quando você redireciona um projeto existente para o .NET 6 ou posterior. No entanto, você pode habilitar o recurso em seu projeto definindo a propriedade ImplicitUsings MSBuild como enable.

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>
</Project>

E estamos conversados......

Assim o .NET SDK agora inclui implicitamente um conjunto de namespaces padrão para projetos C# que se destinam ao .NET 6 ou posterior e usam um dos seguintes SDKs:

Microsoft.NET.Sdk
// <autogenerated />
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;
Microsoft.NET.Sdk.Web
// <autogenerated />
// Microsoft.NET.Sdk related global usings plus the following
global using global::System.Net.Http.Json;
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;
Microsoft.NET.Sdk.Worker
// <autogenerated />
// Microsoft.NET.Sdk related global usings plus the following
global using global::Microsoft.Extensions.Configuration;
global using global::Microsoft.Extensions.DependencyInjection;
global using global::Microsoft.Extensions.Hosting;
global using global::Microsoft.Extensions.Logging;

"Disse-lhe Jesus: Porque me viste, Tomé, creste; bem-aventurados os que não viram e creram."
João 20:29

Referências:


José Carlos Macoratti