連載
» 2002年11月27日 00時00分 公開

連載 改訂版 C#入門:第15章 C#の配列機能 (2/4)

[川俣晶(http://www.autumn.org/),(株)ピーデー(http://www.piedey.co.jp/)]

15-3 参照型の配列

 ここまでのサンプル・ソースは整数型を使って記述してきたが、ほかの値型のデータ型でも同様に扱うことができる。しかし、参照型に関しては、同じとはいかない。List 15-4に、実際に同じように使えないサンプル・ソースを示す。

  1: using System;
  2:
  3: namespace Sample004
  4: {
  5:   class Class1
  6:   {
  7:     [STAThread]
  8:     static void Main(string[] args)
  9:     {
 10:       string [] ar = new string[10];
 11:       for( int i=0; i<10; i++ )
 12:       {
 13:         // Console.WriteLine( ar[i].Length );  // 実行時にnullを参照したというエラーになる
 14:       }
 15:       for( int i=0; i<10; i++ )
 16:       {
 17:         ar[i] = (i*2).ToString();
 18:       }
 19:       for( int i=0; i<10; i++ )
 20:       {
 21:         Console.WriteLine( ar[i].Length );
 22:       }
 23:     }
 24:   }
 25: }

List 15-4

 これを実行するとFig.15-4のようになる。

Fig.15-4

 ここで注目すべきは13行目である。配列を宣言した直後の値を入れる前の状態でそれを参照しようとすると、nullを参照したというエラーになってしまう。これは、参照型の配列インスタンスをnewで作成しても、中身はnullのままでインスタンスは作成されていないことによって起こる現象である。つまり、参照型を配列変数で使うには、配列のインスタンスを作るだけでは十分ではなく、それに加えて、個々の要素のインスタンスも作成しなければならないということである。要素の数が10個なら、配列自身と要素を合わせて計11回のnewを行う必要がある。なお、このサンプル・ソースでは、17行目のToStringメソッドの中で文字列がnewされている。

 念のために17行目で何が起きているかを詳しく説明する。「ar[i]」というのは、もちろん、i番目の配列arを示している。イコールの後半の値が、ここに格納される。さて、イコールの後ろはというと、まず、「i*2」という式が計算されている。もちろん、iも2も整数なので、2倍しているということだ。そして、その計算結果に、いきなりToStringメソッドがくっついている。整数型の数値は、int(正式にはSystem.Int32)というstructの値である。このstructはメソッドを持っている。そのメソッドの中の1つが、ToStringである。このメソッドの機能は文字列に変換することなので、数値は文字列に変換される。その結果、文字列型の配列に、素直に入れることが可能になるのである。

15-4 初期化と省略構文

 配列を宣言する際に、決まり切った値をあらかじめ決め打ちで入れてしまいたい場合がある。これを実現するために、C#では、配列の作成時に初期値を指定することができる。また、宣言の構文には省略構文が存在する。List 15-5のサンプル・ソースでそれを説明する。

  1: using System;
  2:
  3: namespace Sample005
  4: {
  5:   class Class1
  6:   {
  7:     [STAThread]
  8:     static void Main(string[] args)
  9:     {
 10:       int [] ar1 = new int [4] { 0, 1, 2, 3 };
 11:       int [] ar2 = new int [] { 0, 1, 2, 3 };
 12:       int [] ar3 = { 0, 1, 2, 3 };
 13:       for( int i=0; i<4; i++ )
 14:       {
 15:         Console.WriteLine( "{0},{1},{2}", ar1[i], ar2[i], ar3[i] );
 16:       }
 17:     }
 18:   }
 19: }

List 15-5

 これを実行するとFig.15-5のようになる。

Fig.15-5

 まず、基本的な構文は10行目で示すようなものである。「int [] ar1 = new int [4]」の部分はすでに解説したとおりの意味を持つ。問題は、それに続く「 { 0、1、2、3 }」である。中括弧で囲み、カンマで区切った式のリストを記述している。これを初期化リストという。これにより、配列変数が作成されるときに、その式の値が個々の要素の中に格納される。つまり、10行目のコードが実行された時点ですでに変数ar1の0番目の要素には0が、1番目の要素には1が……というように値が格納済みになるのである。

 初期化リストが指定されている場合、11行目のように、newに対応する要素数を記述しないという方法も採れる。省略できるのは、初期化リストの中の項目数を数えれば、何個の要素を持つ配列になるべきかが明らかに分かるためだ。

 さらに突き詰めていくと、12行目のように、newもデータ型も角括弧も書かず、ただ初期化リストだけをイコール記号の右側に置くという書式も可能である。この場合は初期化リストの項目数から要素の数が確定し、データ型は行頭のintから確定可能である。曖昧さはない。

15-5 参照型配列の初期化

 参照型の配列も初期化できる。List 15-6はClass1クラスの配列変数を初期化リストで初期化した例である。

  1: using System;
  2:
  3: namespace Sample006
  4: {
  5:   class Class1
  6:   {
  7:     private int n;
  8:     public Class1( int param )
  9:     {
 10:       this.n = param;
 11:     }
 12:     [STAThread]
 13:     static void Main(string[] args)
 14:     {
 15:       Class1 [] ar = new Class1 [] { new Class1(1), new Class1(2), new Class1(3) };
 16:       for( int i=0; i<3; i++ )
 17:       {
 18:         Console.WriteLine( ar[i].n );
 19:       }
 20:     }
 21:   }
 22: }

List 15-6

 これを実行するとFig.15-6のようになる。

Fig.15-6

 ここでポイントになるのは15行目の初期化リストの中に、そのものずばり、Class1クラスのインスタンスを作成するnewを書き込んでいることである。このような書き方も可能である。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

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

メールマガジン登録

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