ジェネリック・クラスで変わるC#とVBのコレクション特集C#&VBジェネリック超入門(前編)(1/4 ページ)

この新機能を使えばコレクション・クラスの利用が安全かつ効率的に! ちょっと難しいC# 2.0やVB 2005の「ジェネリック」を丁寧に解説。

» 2006年02月11日 00時00分 公開
[遠藤孝信,デジタルアドバンテージ]
特集C#&VBジェネリック超入門
Insider.NET

 

「特集C#&VBジェネリック超入門」のインデックス

連載目次

 Visual Studio 2005の登場に合わせてバージョンアップしたC# 2.0(以下、C#)やVisual Basic 2005(以下、VB)には、たくさんの新機能が導入されています。その中でもプログラマにとって今後欠かせない機能となるのは、やはり「ジェネリック」(Generics)です。

 しかしC#やVBのビギナーにとって、ジェネリックは少々分かりづらい機能でもあります。本稿では2回にわたり、ジェネリックにより何ができるのか、どのように使うのかといったジェネリックの基本事項を分かりやすくまとめてみます。

ジェネリックとは?

 ジェネリックとは、簡単にいうと、特定の型(クラス)に依存しないクラスやメソッドを記述するための仕組みです。この仕組みは、クラス、構造体、インターフェイス、メソッド、デリゲートに適用でき、ジェネリックの仕組みを使ったクラスやメソッドは、「ジェネリック・クラス」や「ジェネリック・メソッド」などと呼ばれます。

 実際には、ジェネリックはコレクション(コレクション・クラス)を便利に利用/実装するための仕組みといえます。コレクションとは、複数のオブジェクトをまとめて管理するためのもので、代表的なものにリストやハッシュテーブルなどがあります(リストは配列と操作方法が似ていますが、配列がサイズ固定なのに対してリストはオブジェクトをいくつでも追加できます)。

 Visual Studio 2005に含まれる.NET Framework 2.0のクラス・ライブラリには、このジェネリックの機能を使用して実装されたコレクションが多数追加されています。このため、それらの新しいコレクションを利用すれば、以前の1.xのころに比べて、プログラムをすっきりと効率的に記述できるようになっています。

従来のコレクションの代表:ArrayListクラス

 まずは、.NET Framework 1.xで最もよく使用されたコレクションであろうで「ArrayListクラス」について簡単に振り返ってみます。

 ArrayListクラスはSystem.Collections名前空間に分類されているクラスです。今後利用する機会は減っていくと思われますが、.NET Framework 2.0でももちろんArrayListクラスは利用可能です。

 さて、ArrayListクラスでは、Addメソッドによりコレクションの要素となるオブジェクトを追加していきます(以降のコードでは上がC#、下がVBのコードとなっています)。

ArrayList alist = new ArrayList();

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

Dim alist As New ArrayList

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

Addメソッドによる要素の追加(ArrayList)

 コレクションに追加された要素は、インデクサにより取り出すことができます。しかしArrayListクラスの不便な点の1つは、取り出した要素を扱うのに、元の型にキャストする必要があることでした。

string greeting;
greeting = (string)alist[0]; // キャストが必要

Dim greeting As String
greeting = CType(alist(0), String) ' キャストが必要

インデクサによる要素の取り出し(ArrayList)
VBではDirectCastキーワードでもキャストが可能。

 これは、ArrayListクラスが内部で要素をObject型として取り扱っているためです。文字列型のオブジェクトを格納しても、それを取り出すときにはすべてObject型となってしまいます。これを元に戻すためにキャストが必要となります。

 また、Objectクラスはすべてのクラスの基本クラスであるので、ArrayListクラスはどのような型のオブジェクトも格納できます。このため、ArrayListオブジェクトには、コレクションの要素として、ほかの型のオブジェクトも混ぜることができてしまいます。

Uri site = new Uri("http://www.atmarkit.co.jp");
alist.Add(site); // 要素としてUri型を追加

Dim site As New Uri("http://www.atmarkit.co.jp")
alist.Add(site) ' 要素としてUri型を追加

Addメソッドによる要素の追加(ArrayList)
ArrayListオブジェクトにはどのような型のオブジェクトも追加できる。

 しかし、文字列ばかりを入れたつもりのコレクションに、なぜか誤ってこのようなUri型のオブジェクトを入れてしまうと*、それを取り出すときに、当然ながら文字列型へのキャストは失敗して実行時にエラーとなります。

* ここでUri型を使ったのには特に意味はありません。


// 実行時にキャストに失敗してエラー
greeting = (string)alist[2];

' 実行時にキャストに失敗してエラー
greeting = CType(alist(2), String)

文字列型以外のオブジェクトを文字列型にキャスト(ArrayList)
alistの3番目の要素がUriオブジェクトである場合。コンパイルできるが、実行時に例外が発生する。

 コレクションのすべての要素を順番に処理する場合、foreach文(VBではFor Each文)を使うと便利ですが、関係のない型のオブジェクトが混ざっていると、同様に実行時にエラーとなってしまいます。

foreach (string s in alist) {
   Console.WriteLine(s);
}

For Each s As String In alist
  Console.WriteLine(s)
Next

foreach文による要素の列挙(ArrayList)
alistに文字列以外が含まれている場合、実行時にその要素を取り出すときに例外が発生する。

 以上のコードをまとめたコンパイル可能なソース・コードを以下に示しておきます。

using System;
using System.Collections;

class GenericSample {
  void Sample() {
    // ArrayListクラスのインスタンス化
    ArrayList alist = new ArrayList();

    // 要素の追加
    alist.Add("こんにちわ");
    alist.Add("さようなら");

    string greeting;

    // greeting = alist[0]; // コンパイル・エラー
    greeting = (string)alist[0]; // キャストが必要

    Uri site = new Uri("http://www.atmarkit.co.jp");
    alist.Add(site); // 要素としてUri型を追加

    // 実行時にキャストに失敗してエラー
    greeting = (string)alist[2];

    // 実行時に3つ目の要素でエラー
    foreach (string s in alist) {
       Console.WriteLine(s);
    }
  }

  static void Main() {
    GenericSample gs = new GenericSample();
    gs.Sample();
  }
}

Imports System
Imports System.Collections

Class GenericSample
  Sub Sample()
    ' ArrayListクラスのインスタンス化
    Dim alist As New ArrayList

    ' 要素の追加
    alist.Add("こんにちわ")
    alist.Add("さようなら")

    Dim greeting As String

    ' greeting = alist(0) ' コンパイル・エラー
    greeting = CType(alist(0), String) ' キャストが必要

    Dim site As New Uri("http://www.atmarkit.co.jp")
    alist.Add(site) ' 要素としてUri型を追加

    ' 実行時にキャストに失敗してエラー
    greeting = CType(alist(2), String)

    ' 実行時に3つ目の要素でエラー
    For Each s As String In alist
      Console.WriteLine(s)
    Next
  End Sub
End Class

Module Module1
  Sub Main()
    Dim gs As New GenericSample
    gs.Sample()
  End Sub
End Module

ArrayListクラスを使用したサンプル・プログラム

 次にジェネリック版ArrayListクラスである、Listジェネリック・クラスを見ていきます。

       1|2|3|4 次のページへ

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

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

メールマガジン登録

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