
Hace unos días hablábamos de las directivas using
globales, un interesante añadido a C# 10 que permite importar espacios de nombres en todos los archivos de código del proyecto, sin necesidad de repetir cientos de veces las mismas líneas en sus encabezados. Simplemente, si un namespace es interesante para nuestro proyecto, lo declaramos como global en algún punto y será lo mismo que si lo hubiéramos hecho en cada uno de los archivos .cs:
global using System;
global using System.Text;
global using System.Text.Json;
global using MyProject.Model;
...
Bien podían haberlo dejado aquí porque ya es una mejora sustancial respecto a lo que tenemos, pero no, el equipo de diseño de C# sigue introduciendo detalles que pueden hacernos la vida más sencilla. Es el caso de los implicit usings que, de la misma forma, acompañan a .NET 6 y C# 10.
Importación implícita de namespaces
El hecho que hay detrás de esta característica es bien simple: hay ciertos espacios de nombres cuya importación que son casi obligatorios en función del tipo de proyecto que estemos desarrollando. Por ejemplo, en casi todos los proyectos encontraremos referencias a System
, System.Collection.Generics
o System.Linq
. O si programamos una aplicación web ASP.NET Core, es habitual que acabemos importando namespaces como Microsoft.AspNetCore.Builder
, Microsoft.AspNetCore.Routing
o System.Net.Http.Json
.
.NET 6 importará automáticamente ciertos espacios de nombres en función del tipo de proyecto, que viene dado por el SDK definido en la primera línea del archivo .csproj
, como el siguiente, correspondiente a un proyecto Web:
<Project Sdk="Microsoft.NET.Sdk.Web">
...
</Project>
En función de este SDK, se importarán los siguientes namespaces:
SDK | Namespaces importados |
---|---|
Microsoft.NET.Sdk | System System.Collections.Generic System.IO System.Linq System.Net.Http System.Threading System.Threading.Tasks |
Microsoft.NET.Sdk.Web | System.Net.Http.Json Microsoft.AspNetCore.Builder Microsoft.AspNetCore.Hosting Microsoft.AspNetCore.Http Microsoft.AspNetCore.Routing Microsoft.Extensions.Configuration Microsoft.Extensions.DependencyInjection Microsoft.Extensions.Hosting Microsoft.Extensions.Logging (+ todos los de Microsoft.NET.Sdk) |
Microsoft.NET.Sdk.Worker | Microsoft.Extensions.Configuration Microsoft.Extensions.DependencyInjection Microsoft.Extensions.Hosting Microsoft.Extensions.Logging (+ todos los de Microsoft.NET.Sdk) |
Para evitar conflictos con clases existentes, esta característica está desactivada por defecto, de forma que si migramos un proyecto de .NET 5 a .NET 6 seguro que no se romperá nada. Pero para proyectos nuevos, ya habilita de serie en las nuevas plantillas, usando la siguiente configuración en el .csproj
:
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
...
</PropertyGroup>
Internamente, cuando los implicit usings están habilitados, se generará durante la compilación un archivo llamado [ProjectName].GlobalUsings.g.cs
en la carpeta obj
. Por ejemplo, este es el contenido que podemos encontrar en una aplicación web:
// <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;
Aunque este proceso sea automático, podemos utilizar el .csproj
para ajustar los espacios de nombre incluidos en este archivo, como ya vimos en el post sobre los usings globales. En el siguiente ejemplo vemos cómo podríamos eliminar System
y añadir MyProject.Model
de forma muy sencilla:
<ItemGroup>
<Using Remove="System" />
<Using Include="MyProject.Model" />
</ItemGroup>
En definitiva, la idea no está nada mal y es una de las piezas que permite conseguir algunas cosas realmente espectaculares, como las que podemos ver al crear nuevos proyectos de consola, cuyo código veremos que consiste en una única línea, o las cuatro o cinco líneas que costará poner en marcha un servidor ASP.NET Core. A cambio, eso sí, tendremos que aceptar el cierto grado de "magia" que este tipo de comportamientos implícitos añaden a nuestras aplicaciones.
Publicado en Variable not found.
Aún no hay comentarios, ¡sé el primero!
Enviar un nuevo comentario