連載
» 2016年06月15日 05時00分 UPDATE

.NET TIPS:構文:クラス名を書かずに静的メソッドを呼び出すには?[C# 6.0]

C# 6.0では「using static」で特定のクラスを指定することで、そのクラスの静的メソッドなどをクラス名を書かずにそのまま使用できるようになる。

[山本康彦,BluewaterSoft/Microsoft MVP for Windows Development]
「.NET TIPS」のインデックス

連載目次

対象:Visual Studio 2015(C# 6.0)以降


 静的メソッド(static method)や列挙型(enum)の列挙値などを記述するとき、いちいち型名を書くのが面倒だと思ったことはないだろうか? C# 6.0からは、usingディレクティブを使って簡潔に書けるようになった。本稿ではその使い方を説明する。

using staticの基本

 コードの冒頭で、「using static」に続けて静的メンバー(静的メソッドや列挙値など)を持っているクラスや列挙型などを記述する。これで、コード本体では静的メンバーだけを記述すれば済むようになる(次のコード)。

using static System.Console; // クラス

// 以下の2つを使うには、Microsoft.VisualBasicへの参照がプロジェクトに必要
using static Microsoft.VisualBasic.Strings; // クラス
using static Microsoft.VisualBasic.VbStrConv; // 列挙型

class Program
{
  static void Main(string[] args)
  {
    // System.Consoleの静的メソッドを使用
    Write("Hello, ");
    WriteLine("world!");
    // ⇒ Hello, world!

    // Visual Basicの関数も、まるでC#の機能のように使える
    var s = StrConv("ゼンカク→ハンカク", Narrow);
    WriteLine(s);
    // ⇒ ゼンカク→ハンカク

#if DEBUG
    ReadKey();
#endif
  }
}

using staticを使ったコンソールアプリの例
Write/WriteLine/ReadKeyは、System.Consoleクラスの静的メソッド。
StrConvは、Microsoft.VisualBasic.Stringsクラスの静的メソッド。
Narrowは、Microsoft.VisualBasic.VbStrConv列挙型の列挙値である。

IntelliSenseも対応

 using staticを使った場合でも、IntelliSenseは(クラス名を書かなくても)候補を提示してくれる(次の画像)。

IntelliSenseはusing staticにも対応している IntelliSenseはusing staticにも対応している
前述のコードのように、冒頭には「using static System.Console;」と記述してある。System.Consoleクラスの静的メソッド名を少し打った時点で、IntelliSenseが候補を表示してくれた。候補にはクラス名も表示されているので、間違いなく目的の静的メソッドだと分かる。

応用:型名の衝突を回避

 using staticは、型名が衝突するときの解決策としても使える。例えば、次の2つの名前空間の両方にAssertクラスがある*1。そしてどちらのクラスの静的メソッドも使いたいとしよう。

  • Microsoft.VisualStudio.TestPlatform.UnitTestFramework
  • Microsoft.VisualStudio.TestPlatform.UnitTestFramework.AppContainer

*1 この名前空間はユニバーサルWindowsプラットフォーム用のユニットテストフレームワークなのだが、MSDNにドキュメントがまだ掲載されていない。興味のある方は、筆者のブログ記事「MSTest‐Windows ストア アプリ開発の暗黒大陸」を参考にしてほしい。


 従来は、次のコードのようにusingエイリアスディレクティブを使って、片方のクラス名に別名を付けて使っていた。

using System;
using System.Threading.Tasks;

// 前者の名前空間は普通にusing
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;

// usingエイリアスディレクティブで、後者のAssertクラスには別名を定義
using AppContainerAssert =
  Microsoft.VisualStudio.TestPlatform.UnitTestFramework.AppContainer.Assert;

……省略……

// 別名を付けていない方のAssertクラスの静的メソッドを使う
Assert.AreEqual<string>("5", ((int)5.6).ToString());

// 別名を付けた方のAssertクラスの静的メソッドを使う
await AppContainerAssert.ThrowsException<NotImplementedException>(
  () => { throw new NotImplementedException(); }
);

クラス名の衝突を回避する従来の書き方(usingエイリアスディレクティブ)
クラス名が衝突している場合、片方のクラスは名前空間をフルに記述するか、このコードのようにusingエイリアスディレクティブでクラスの別名を定義して使っていた。

 using staticを使うと、コンパイラやIntelliSenseが静的メソッドの所属するクラスを適切に判断してくれる。クラス名が衝突していても、コード本体に長い名前空間やクラス名の別名を書かなくてよいのだ(次のコード)。

using System;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;

// 同名のクラス(名前空間は異なる)を2つ、using staticする
using static Microsoft.VisualStudio.TestPlatform.UnitTestFramework.Assert;
using static
  Microsoft.VisualStudio.TestPlatform.UnitTestFramework.AppContainer.Assert;

……省略……

// 前者のAssertクラスの静的メソッドを呼び出す
AreEqual<string>("5", ((int)5.6).ToString());

// 後者のAssertクラスの静的メソッドを呼び出す
await ThrowsException<NotImplementedException>(
  () => { throw new NotImplementedException(); }
);

using staticでクラス名の衝突を回避する例
2つのAssertクラス(名前空間は異なる)をusing staticしている。
AreEqual静的メソッドは前者のAssertクラス、ThrowsException静的メソッドは後者のAssertクラスの静的メンバーである。

まとめ

 using staticを使うと、コード本体では静的メンバーを呼び出すときに型名を省略できる。また、この機能は型名の衝突回避にも応用できる(片方は静的メンバーだけを使う場合)。

「.NET TIPS」のインデックス

.NET TIPS

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

Focus

- PR -

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。