【3/18〜】Amazon、VMwareが語る『クラウドの未来』 スラッシュドット    はてなブックマーク  Yahoo!ブックマークに登録  印刷
   

特集

C#&VBジェネリック超入門(前編)

ジェネリック・クラスで変わる
C#とVBのコレクション

デジタルアドバンテージ 遠藤 孝信
2006/02/11
Page1 Page2 Page3 Page4

ジェネリック・クラスの記述方法

 ここで簡単に、ジェネリック・クラスの記述方法についても見ておきましょう。

 以下は、Listジェネリック・クラスの仕様をまねたMyListジェネリック・クラスの実装例です。取りあえずAddメソッドとインデクサだけを実装しています。

public class MyList<T> {
  T[] _list = new T[1000]; // 要素は最大1000個まで
  int _size = 0;

  // Addメソッド
  public void Add(T item) {
    _list[_size++] = item;
  }

  // インデクサ
  public T this[int index] {
    get {
      return _list[index];
    }

    set {
      _list[index] = value;
    }
  }
}
Public Class MyList(Of T)
  Dim _list(1000) As T ' 要素は最大1000個まで
  Dim _size As Integer = 0

  ' Addメソッド
  Public Sub Add(ByVal item As T)
    _list(_size) = item
    _size += 1
  End Sub

  ' デフォルト・プロパティ(インデクサとして機能)
  Default Public Property Item(ByVal index As Integer) As T
    Get
      Return _list(index)
    End Get
    Set(ByVal value As T)
      _list(index) = value
    End Set
  End Property
End Class
ジェネリックを使用したMyListクラスの実装
格納する要素が1000を超えた場合にはエラーとなる。またインデクサでのインデックス番号の範囲チェックも行っていない。

 このように、ジェネリック・クラスの記述では、型パラメータを「T」とした場合、Tというクラスがあるかのようにフィールドやメソッドを記述していきます。

 これまでに「T」の部分が具体的なクラス名になっているようなクラスを記述されたことがあるかもしれません。例えば「T」の部分がすべて「Employee」になっているようなEmployeeクラス専用のコレクション・クラスなどです。

 ジェネリックの導入により、その「T」部分が自動的に置き換えられる、汎用的なコレクション・クラスが記述可能となったわけです。

 なお、型パラメータである「T」は単なるパラメータの名前であり、メソッドのパラメータと同じで、好きな名前を付けることができます。ただし名前付けのガイドラインは用意されています*。型パラメータが1つだけの場合は「T」がよく用いられます。

*「型パラメータの名前付けのガイドライン」を参照してください。

 念のために、上記のMyList<T>クラスを、文字列型とDateTime構造体で使用したサンプル・プログラムを次に示しておきます。

// MyList<T>クラスを利用

using System;

public class GenericSample {
  static void Main() {
    // 文字列用のリスト
    MyList<string> strings = new MyList<string>();

    strings.Add("こんにちわ");
    strings.Add("さようなら");

    string hello = strings[0];
    Console.WriteLine(hello);
    // 出力:こんにちわ

    // DateTime用のリスト
    MyList<DateTime> datetimes = new MyList<DateTime>();

    datetimes.Add(DateTime.Today);
    datetimes.Add(DateTime.MaxValue);

    DateTime today = datetimes[0];
    Console.WriteLine(today);
    // 出力例:2006/02/09 0:00:00
  }
}
' MyList(Of T)クラスを利用

Module Module1
  Sub Main()
    ' 文字列用のリスト
    Dim strings As New MyList(Of String)
    strings.Add("こんにちわ")
    strings.Add("さようなら")

    Dim greeting As String = strings(0)
    Console.WriteLine(greeting)
    ' 出力:こんにちわ

    ' DateTime用のリスト
    Dim datetimes As New MyList(Of DateTime)
    datetimes.Add(DateTime.Today)
    datetimes.Add(DateTime.MaxValue)

    Dim today As DateTime = datetimes(0)
    Console.WriteLine(today)
    ' 出力例:2006/02/09 0:00:00
  End Sub
End Module
MyListジェネリック・クラスを使用したサンプル・プログラム

【コラム】 型パラメータの制約

 ジェネリック・クラスを記述するとき、型パラメータに指定される型を制限する必要が出てくる場合があります。

 例えば、型パラメータの型(以下、Tと省略)のオブジェクトのメソッドを呼び出すようなコードを記述する場合、Tには必ずそのメソッドが実装されていなければ困ります。あるいは、Tのインスタンスを生成する(new T()する)ようなコードを記述する場合には、Tにパブリックな(パラメータを持たない)コンストラクタがなければ困ります。

 ジェネリック・クラスでこういった制約(constraints)を記述するには、C#ではwhereキーワード、VBでは「Of T」の後にAsキーワードを使います。

 以下に、記述可能な制約のパターンの一覧を実際のコードで示します(このコードはコンパイル可能です)。

class MyGenericClass1<T> where T : struct {
  // 制約:Tは構造体
}

class MyGenericClass2<T> where T : class {
  // 制約:Tはクラス
}

class MyGenericClass3<T> where T : new() {
  // 制約:Tはインスタンス化可能
}

class MyGenericClass4<T> where T : MyOtherClass {
  // 制約:TはMyOtherClassクラスを継承
}

class MyGenericClass5<T> where T : IMyInterface {
  // 制約:TはIMyInterfaceインターフェイスを実装
}

class MyGenericClass6<T, U> where T : U {
  // 制約:Tは別の型パラメータUを継承
}

//////////////////////////////////////////////////
class MyOtherClass {
  // とあるクラス
}

interface IMyInterface {
  // とあるインターフェイス
}
Class MyGenericClass1(Of T As Structure)
  ' 制約:Tは構造体
End Class

Class MyGenericClass2(Of T As Class)
  ' 制約:Tはクラス
End Class

Class MyGenericClass3(Of T As New)
  ' 制約:Tはインスタンス化可能
End Class

Class MyGenericClass4(Of T As MyOtherClass)
  ' 制約:TはMyOtherClassクラスを継承
End Class

Class MyGenericClass5(Of T As IMyInterface)
  ' 制約:TはIMyInterfaceインターフェイスを実装
End Class

Class MyGenericClass6(Of T As U, U)
  ' 制約:Tは別の型パラメータUを継承
End Class

''''''''''''''''''''''''''''''''''''''''''''''''''
Class MyOtherClass
  ' とあるクラス
End Class

Interface IMyInterface
  ' とあるインターフェイス
End Interface
記述可能な制約のパターンの一覧

 なおここでは説明は割愛しますが、1つの型パラメータに対して複数の制約を指定可能です。


 INDEX
  [特集]
  C#&VBジェネリック超入門(前編)
  ジェネリック・クラスで変わるC#とVBのコレクション
    1.従来のコレクションの代表:ArrayListクラス
    2.ジェネリックを使った新しいコレクション:Listジェネリック・クラス
  3.ジェネリック・クラスの記述方法
    4.Hashtableクラスを置き換えるDictionaryジェネリック・クラス
 
  C#&VBジェネリック超入門(後編)
  ジェネリックなメソッドやデリゲートがもたらす新スタイル
    1.ジェネリック・メソッド − ArrayクラスのIndexOfメソッド
    2.ジェネリック・デリゲート − Action<T>デリゲート
    3.Action<T>デリゲートを使用するList<T>クラスのForEachメソッド
    4.Comparison<T>デリゲートを使用するList<T>クラスのSortメソッド
 

ホワイトペーパーTechTargetジャパン

Insider.NET フォーラム 新着記事

@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

RSSフィード

スキルアップ/キャリアアップ(JOB@IT)

.NET開発者中心に生まれ変わりました

.NET開発者中心コーナー

- PR -

- PR -

お勧め求人情報

キャリアアップ 〜JOB@IT
@IT Special -PR-
  上司や部下、部署内メンバーとの情報共有
を“ガラッ”と変えるコラボツールとは?

New!
  おばかアプリ選手権、第4弾開催中!!
ムダにカッコよくてくだらない作品求ム!

  社内ファイルサーバを“クラウド”に統合
VPN直結「クラウド型ストレージ」を紹介

  Twitterのアカウントはなぜ突破された?
メールによる新手の攻撃手法とその対策

  もう仮想化のお試しフェイズは終わりだ!
Hyper-V 2.0が基幹システムも仮想化

  美人!? まあまあ? 気になる いやし系!!
PV急増で「美人時計」がとった手段とは?

  クライアント企業から求められる人材
⇒IT技術と経営戦略を併せ持つ「戦略家」

  .NET編集長が実践する「技術情報検索術」
サンプル・コードを簡単に探す“技”は?

  業務効率と情報セキュリティ対策を両立!
手間なく確実に機密情報を守る方法とは?

  直属上司が海外にいるのエンジニアに見る
【実例】場所に捉われないワークスタイル

  進化を続ける富士通ストレージETERNUS DX
製品開発者の自信を裏付けるものとは何か

  運用管理の課題を“2つの観点”から分析
ユーザー満足度の高い「仮想環境」とは?

  【CTC事例】約30の基幹システムを統合!
膨大なバッジジョブを制御した方法は?

  仮想化すればコストは削減できるか?
仮想化に必要な「3つの視点」を解説する

  その数、なんと400台以上! グループ内
サーバの「統合管理」によるメリットは?