特集

.NET開発者のためのPDC 2003レポート

吉松 史彰
2003/11/12

Page1 Page2 Page3

Whidbeyの新機能

 YukonとLonghornについての詳しい解説はまたの機会に譲ることにして、ここではWhidbeyの新機能を概観してみたい。

 まずは、開発者(主にプログラマ)にとって最も重要であると思われる2つの新機能「Generics」と「Partial Types」である。

新機能:Generics(ジェネリック)

 Visual Basic 6.0以前のバリアント型や、.NET FrameworkのObject型などは、さまざまなオブジェクトを同列に扱うことができるため、オブジェクトの集合体(コレクション)などを実装するときに便利だった。.NET Frameworkでも、HashtableクラスやArrayListクラスなどでObject型が利用されている。しかし、Object型を使ってしまうと、コンパイル時にはオブジェクトの型が無視されてしまうため、実行時例外の温床にもなりがちだった。例えば、従来のArrayListクラスでは次のようなコードを記述できた。このコードはコンパイルできてしまうが、もちろん、実行時に例外を発生させる。

using System;
using System.Collections;

class App {
  static void Main() {
    ArrayList ar = new ArrayList(3);
    string s = "Hello world!";
    ar.Add(s);

    int i = (int)ar[0]; // 実行時に例外が発生
    Console.WriteLine(i);
  }
}
コンパイル時に検出できない例外発生の例
ArrayListクラスはObject型オブジェクトのコレクション・クラスであるためどのような型でも追加できるが、それを取り出すときにキャストする型を誤ると容易に実行時例外が起こる。

 Genericsは、動的に型を作成できるメカニズムである。配列が既存の型定義を利用して新しい型をソースコード中に動的に定義する機能であるのと同様に、Genericも既存の型定義から新しい型を動的に定義する機能であるということができる。上記のコードは、Genericsを使えば次のように書ける。重要な点は、このコードのエラーはコンパイル時に検出されることである。

using System;
using System.Collections.Generic;

class App {
  static void Main() {
    List<string> ar = new List<string>(3);
    string s = "Hello world!";
    ar.Add(s);

    int i = (int)ar[0]; // error CS0030: Cannot convert type 'string' to 'int'.
    Console.WriteLine(i);
  }
}
動的に型を作成可能なWhidbeyのGenerics
新しいSystem.Collections.Generic名前空間のListクラスは、要素の型を指定可能なコレクション・クラスである。誤った型へのキャストはコンパイル時に検出できる。

 Genericsは型を作成するときにだけ使うわけではない。メソッドやデリゲートの定義にも利用できる。例えば、現在のC#を利用する限り、次のような従業員のコレクションを表すクラス(Employees)を作成すると、総称的なEmployeeクラスのオブジェクトを返すメソッド(以下の例ではインデクサ)を実装して呼び出し側にキャストしてもらうか、またはCommissioned(歩合制)の従業員とSalaried(給与制)の従業員を別々に取得するメソッドを定義するしかない。

using System;
using System.Collections;

class Employee {
  internal string Name;
  internal string ID;
}

class Commissioned : Employee {
  internal double Commission;
}

class Salaried : Employee {
  internal double Salary;
}

class Employees {
  private Hashtable list;
  internal Employee this[string ID] {
    get { return (Employee)list[ID]; }
  }
  internal Commissioned GetCommissioned(string ID) {
    return list[ID] as Commissioned;
  }
  internal Salaried GetSalaried(string ID) {
    return list[ID] as Salaried;
  }
}

class App {
  static void Main() {
    Employees emps = new Employees();
    // 従業員を読み込むコードは省略……
    Commissioned tanaka = (Commissioned)emps["941434"];
    Commissioned tanaka = emps.GetCommissioned("941434");
    Salaried tanaka = emps.GetSalaried("941434");
  }
}
インデクサを利用したコレクション・クラスの実装例
この例では、コレクション・クラスであるEmployeesクラスのインデクサは、それを使用する側でキャストが必要となる。キャストを使用させないためには、個別のメソッド(この場合にはGetXXXXメソッド)が必要となる。

 しかし、Genericメソッドを使えば、Employeesクラスのコードは次のように簡単になる。

class Employees {
  private Hashtable list;
  internal T Get<T>(string ID) where T : Employee {
    return list[ID] as T;
  }
}
WhidbeyのGenericメソッドを使用して書き換えたEmployeesクラス
Genericメソッドでは、特定の型に縛られない汎用的なメソッドが記述可能だ。この例ではメソッドの戻り値を特定せずにメソッドを記述している。

 このコードは次のように利用することになる。呼び出し側のコードに大きな変化はないが、クラスの実装ははるかに楽になっている。

class App {
  static void Main() {
    Employees emps = new Employees();
    // 従業員を読み込むコードは省略……
    Commissioned tanaka = (Commissioned)emps.Get<Employee>("941434");
    Commissioned sato = emps.Get<Commissioned>("941434");
    Salaried suzuki = emps.Get<Salaried>("941434");
  }
}
Genericメソッド呼び出しの記述例
戻り値の型を指定するメソッドの呼び出しにより、誤ったキャストによる実行時例外をなくすことができる。

新機能:Partial Types(パーシャル・タイプ)

 Whidbey時代の開発者にとって、Genericsと同じくらい、あるいはそれ以上に重要になるのが、Partial Typesの機能である。現在のVB.NETやC#では、Javaとは違い、1つの物理的なファイルに複数の(しかもPublicにアクセスできる)型を記述できる。しかしその逆、つまり1つの型を複数のファイルに分けて記述することはできない。従来のC++において、ヘッダ・ファイル(.h)と実装ファイル(.cpp)を使い分けるようなことは、現在のVB.NETとC#ではできないのである。Partial Typeはこれを可能にする技術である。

 例えば、現在のVisual Studio .NETでWindowsアプリケーションを作成する場合、レイアウトに関するコードは#region〜#endregionで囲むことにより見えないようにしている。それがWhidbey時代のVisual Studio .NETでは、完全にファイルを分けて記述できるようになるため、コード・エディタ上のコードがよりすっきりすることになる。つまり、現在のASP.NETのWebフォームと同じように、Windowsアプリケーションでも「コードビハインド」が実現できるようになるのである。いまのところは、レイアウトのためのファイルもコードのファイルも両方ともC#やVB.NETで記述されるので、そのような使い方はばかばかしいと思われるかもしれない。だが、Longhornが現実化すると、この機能が大きな意味を持つことになる。

 デザイナとコードで完全にファイルを分けてしまうということ自体は、現在でもすでにASP.NETでは実現されている。現在のコードビハインド機能は、実行時に.aspxファイルをパーサーにかけてC#やVB.NETのコードに変換する際に、もともと記述してあるコードビハインドのクラスから継承して新しいクラスを作ることで実現されている。非常に巧妙なやり方ではあるが、このように無意味に継承を利用すると、実行時の型情報が無意味に膨らんでしまうという欠点も併せ持つことになる。Whidbey時代のASP.NETは、上記のWindowsアプリケーションと同じように、Partial Typesの機能を使ってコードビハインドを実現するため、無意味な情報が減ることになる。


 INDEX
  [特集].NET開発者のためのPDC 2003レポート
     1.PDC 2003で明らかになったこと
   2.Whidbeyの新機能(1)
     3.Whidbeyの新機能(2)
 


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 記事ランキング

本日 月間