.NET TIPS

長いジェネリック・クラスの名前を短く記述するには?[2.0のみ、C#、VB]

デジタルアドバンテージ 遠藤 孝信
2006/04/28

 「TIPS:ハッシュテーブル(Dictionaryクラス)を値でソートするには?」で示しているサンプル・プログラムのように、ジェネリック・クラスを使ったコーディングは、各行が長く複雑になりがちだ。

 例えば、型パラメータに文字列型と整数型を指定するKeyValuePair構造体(System.Collections.Generic名前空間)の要素を持つListクラス(System.Collections.Generic名前空間)は次のように記述しなければならない。

List<KeyValuePair<string, int>>
List(Of KeyValuePair(Of String, Integer))
KeyValuePair構造体の要素を持つListクラスの記述(上:C#、下:VB)

 このような記述が煩雑な場合には、C#ではusingディレクティブ、VBではImportsステートメントを用いてクラス名に短い別名を付け、その別名を用いてコードを簡潔に記述できる。

 まず以下に別名の定義例を示す。

using StrIntList =
  System.Collections.Generic.List<
    System.Collections.Generic.KeyValuePair<string, int>>;
Imports StrIntList = _
  System.Collections.Generic.List(Of _
    System.Collections.Generic.KeyValuePair(Of String, Integer))
別名の定義例(上:C#、下:VB)

 usingやImportsは通常、利用するクラスの名前空間の指定に用いられるが、別名の定義はこれらのキーワードが持つ、もう1つの機能だ。

 このような別名を多用すれば、以下のようなコードの書き換えが可能となる(書き換え後の完全なソース・コードは後掲)。

Dictionary<string, int> dict = new Dictionary<string, int>();
makeDict(dict);

List<KeyValuePair<string, int>> sorted = sortByValue(dict);

foreach (KeyValuePair<string, int> kvp in sorted) {
  Console.WriteLine(kvp.Key + ":" + kvp.Value);
}
StrIntDict dict = new StrIntDict();
makeDict(dict);

StrIntList sorted = sortByValue(dict);

foreach (StrIntPair kvp in sorted) {
  Console.WriteLine(kvp.Key + ":" + kvp.Value);
}
別名によるC#のコード書き換え例
上:元のコード
下:ジェネリック・クラスに対して別名を使用したコード

Dim dict As New Dictionary(Of String, Integer)
makeDict(dict)

Dim sorted As List(Of KeyValuePair(Of String, Integer)) = sortByValue(dict)

For Each kvp As KeyValuePair(Of String, Integer) In sorted
  Console.WriteLine(kvp.Key & ":" & kvp.Value)
Next
Dim dict As New StrIntDict()
makeDict(dict)

Dim sorted As StrIntList = sortByValue(dict)

For Each kvp As StrIntPair In sorted
  Console.WriteLine(kvp.Key & ":" & kvp.Value)
Next
別名によるVBのコード書き換え例
上:元のコード
下:ジェネリック・クラスに対して別名を使用したコード

 このようにジェネリック・クラスに対して別名を使用すると、ジェネリック・クラスであっても非ジェネリック・クラスのように扱うことができ、コードもかなりすっきりする。

 もちろん別名の定義は非ジェネリック・クラスに対しても可能であり、.NET Framework 1.0のころより使える機能であるが、ジェネリック・クラスの登場により、その有用性が増したといえるだろう。

 以下には、「TIPS:ハッシュテーブル(Dictionaryクラス)を値でソートするには?」のサンプル・プログラム全体を、別名を使って書き換えたものを示しておく。

// genericalias.cs

using System;
using System.Net;
using System.Text.RegularExpressions;
using System.Collections.Generic;

// ジェネリック・クラスに対する別名の定義
using StrIntPair =
  System.Collections.Generic.KeyValuePair<string, int>;

using StrIntDict =
  System.Collections.Generic.Dictionary<string, int>;

using StrIntList =
  System.Collections.Generic.List<
    System.Collections.Generic.KeyValuePair<string, int>>;

//////////////////////////////////////////////////

class GenericAlias {
  static void makeDict(StrIntDict dict) {
    string html;

    // HTMLの取得
    using (WebClient wc = new WebClient()) {
      html = wc.DownloadString("http://www.atmarkit.co.jp/");
    }

    // 単語に分割して、各単語の出現頻度をカウント
    foreach (string s in Regex.Split(html, "\\W")) {
      string word = s.Trim();
      if (word != "") {
        if (dict.ContainsKey(word)) {
          dict[word]++;
        } else {
          dict[word] = 1;
        }
      }
    }
  }

  static void Main() {
    StrIntDict dict = new StrIntDict();
    makeDict(dict);

    StrIntList sorted = sortByValue(dict);
    // sorted.Reverse(); // 逆順にする場合

    foreach (StrIntPair kvp in sorted) {
      Console.WriteLine(kvp.Key + ":" + kvp.Value);
    }
    // 出力例:
    // a:542
    // td:394
    // 0:328
    // width:289
    // tr:284
    // ……
  }

  static StrIntList sortByValue(StrIntDict dict) {
    StrIntList list = new StrIntList(dict);

    // Valueの大きい順にソート
    list.Sort(
      delegate(StrIntPair kvp1, StrIntPair kvp2) {
        return kvp2.Value - kvp1.Value;
      });
    return list;
  }
}

// コンパイル方法:csc genericalias.cs
別名を使って書き換えたC#のサンプル・プログラム(genericalias.cs)

' genericalias.vb

Imports System
Imports System.Net
Imports System.Text.RegularExpressions
Imports System.Collections.Generic

' ジェネリック・クラスに対する別名の定義
Imports StrIntPair =
  System.Collections.Generic.KeyValuePair(Of String, Integer)

Imports StrIntDict =
  System.Collections.Generic.Dictionary(Of String, Integer)

Imports StrIntList =
  System.Collections.Generic.List(Of
    System.Collections.Generic.KeyValuePair(Of String, Integer))

''''''''''''''''''''''''''''''''''''''''''''''''''

Class DictionarySortByValue
  Shared Sub makeDict(ByVal dict As StrIntDict)
    Dim html As String

    ' HTMLの取得
    Using wc As New WebClient()
      html = wc.DownloadString("http://www.atmarkit.co.jp/")
    End Using

    ' 単語に分割して、各単語の出現頻度をカウント
    For Each s As String In Regex.Split(html, "\W")
      Dim word As String = s.Trim()
      If Not word = "" Then
        If dict.ContainsKey(word) Then
          dict(word) += 1
        Else
          dict(word) = 1
        End If
      End If
    Next
  End Sub

  Shared Sub Main()
    Dim dict As New StrIntDict()
    makeDict(dict)

    Dim sorted As StrIntList = sortByValue(dict)
    ' sorted.Reverse() ' 逆順にする場合

    For Each kvp As StrIntPair In sorted
      Console.WriteLine(kvp.Key & ":" & kvp.Value)
    Next
    ' 出力例:
    ' a:542
    ' td:394
    ' 0:328
    ' width:289
    ' tr:284
    ' ……
  End Sub

  Shared Function hikaku(ByVal kvp1 As StrIntPair, ByVal kvp2 As StrIntPair) As Integer
    ' Valueの大きい順にソート
    Return kvp2.Value - kvp1.Value
  End Function

  Shared Function sortByValue(ByVal dict As StrIntDict) As StrIntList

    Dim list As New StrIntList(dict)

    list.Sort(AddressOf hikaku)
    Return list
  End Function
End Class

' コンパイル方法:vbc genericalias.vb
別名を使って書き換えたVBのサンプル・プログラム(genericalias.vb)

 なお、usingやImportsにより別名を定義する際には、ほかで定義した別名や、名前空間名を省略したクラス名をその定義に含めることはできない。このため、このサンプル・プログラムのように、別名の定義部分だけは各行が長くなってしまう。End of Article

利用可能バージョン:.NET Framework 2.0のみ
カテゴリ:C# 処理対象:言語構文
カテゴリ:Visual Basic 2005 処理対象:言語構文
使用ライブラリ:Dictionaryクラス(System.Collections.Generic名前空間)
使用ライブラリ:KeyValuePair構造体(System.Collections.Generic名前空間)
使用ライブラリ:Listクラス(System.Collections.Generic名前空間)
関連TIPS:ハッシュテーブル(Dictionaryクラス)を値でソートするには?

この記事と関連性の高い別の.NET TIPS
ハッシュテーブル(連想配列)を使うには?(Dictionaryクラス編)[2.0のみ、C#、VB]
ハッシュテーブル(Dictionaryクラス)を値でソートするには?
Dictionaryクラスを簡単に初期化するには?
構文:クラス名を書かずに静的メソッドを呼び出すには?[C# 6.0]
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間