はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【C#】C#10で導入されたMSBuildのプロパティであるImplicitUsingsを用いてglobal usingを暗黙的に定義する方法

はじめに

今回はC#10で導入されたMSBuildのプロパティであるImplicitUsingsについて紹介したいと思います。

learn.microsoft.com

概要

ImplicitUsingsenableに設定すると、Systemなどの名前空間が暗黙的にglobal usingに定義されます。global usingというのはコンパイル内のすべてのファイル (通常はプロジェクト)にusingが適用されるC#10から入った機能です。

<PropertyGroup>
  <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
// XXX.GlobalUsings.g.cs (仕組み的にはSourceGeneratorによりコンパイル時に以下が定義される)
// dotnet buildするとobjの中に入っているので確認できます

// dotnet new consoleでプロジェクトを作成した際にImplicitUsingsで暗黙的に追加される名前空間
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;
// Program.cs

// 本来はこう書かないと行けないが...
System.Console.WriteLine("Hello, World!");

// ImplicitUsingsがenableのおかげでusingを明示的に記述しなくてもよくなる
Console.WriteLine("Hello, World!");

また注意点の一つとして、.NET6以降のC#プロジェクトテンプレートではデフォルトでenableが設定されています。

.NET 6 以降をターゲットとする新しい C# プロジェクトのテンプレートでは、ImplicitUsings は既定で enable に設定されます。

dotnet new consoleを試した様子

実際にconsoleでプロジェクト作成するとImplicitUsingsenableになっていることを確認できます。

$ dotnet new console -f net8.0
<Project Sdk="Microsoft.NET.Sdk">

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

</Project>

プロジェクト SDK の種類とglobal usingの定義

プロジェクトのSDKによって定義されるglobal usingが異なります。

  • Microsoft.NET.Sdk
  • Microsoft.NET.Sdk.Web
  • Microsoft.NET.Sdk.Worker
  • Microsoft.NET.Sdk.WindowsDesktop

learn.microsoft.com

例えばMicrosoft.NET.Sdk.Webでは下記が定義されます。

# ASP.NET Core
$ dotnet new web -f net8.0
// <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;

定義されるglobal usingを編集する

Usingを用いることで、ImplicitUsingsにより定義されるglobal usingを追加・削除することができます。こちらも.NET6 (C#10)からですね。

下を用いると追加できます。

<ItemGroup>
    <Using Include="Microsoft.AspNetCore.Builder" /> 
</ItemGroup>
// XXX.GlobalUsings.g.cs

// <auto-generated/>
global using global::Microsoft.AspNetCore.Builder;


逆に削除したい場合はRemoveを指定します。

<PropertyGroup>
    <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
    <Using Remove="Microsoft.AspNetCore.Builder" />
</ItemGroup>

Alias

UsingAliasを付与すると、名前空間をエイリアスでグローバルに使用することができます。つまりプロジェクト内のどのファイルでもAliasに記述した名前を使って名前空間にアクセスできます。

<ItemGroup>
    <Using Include="Microsoft.AspNetCore.Builder" Alias="Builder"/>
</ItemGroup>
// <auto-generated/>
global using Builder = global::Microsoft.AspNetCore.Builder;

Static

UsingStaticを付与すると以下の意味になります。

<ItemGroup>
    <Using Include="Microsoft.AspNetCore.Http.Results" Static="True" />
</ItemGroup>
// <auto-generated/>
global using static global::Microsoft.AspNetCore.Http.Results;