配列(Array)


POINT C# の配列はひとつのクラスのため Instance を生成する時は new をする。 System.Array クラスから継承される。 次元は N 次元可能で, 宣言. 初期化の構文以外は C, C++ と同じ. 配列は、[ 同じデータ型の多数のデータを集めたもの ]で、個々のデータはインデックス番号で読み書きできる。 __LINK__( ArrayList ) 要素数が 可変の場合は ArrayList をつかう。 WARNING [] は読み書きに使うときには変数名の後に付くが、宣言時には変数名の手前になる。
int []a = new int[10];
// int 型要素が 10 個はいる配列インスタンスを a という名前で作成 int[] a = new int[10]; // data を代入して初期化 // { 1, 2... } 初期化子リスト int[] a = new int[10]{1, 2, 4, 8, 16, 32, 64, 128, 256, 512}; int [] a = { 4, 1, 3, 2, 0 }; // 昇順に Sort System.Array.Sort( a ); // 要素のインデックスを検索する( なければ -1 ) Array.IndexOf( a, 1 ); // 各要素へは , 区切りで指定する a[0,0] = 1; // 3次元以上も同じ int [,,] ar = new int[3,3,3]; Console.Write( ar[0,0,0] ); // 各要素をイテレートする // IEnumerableというインターフェイスの実装を含む。 foreach( int i in a ) { } // 参照型の配列の初期化 Class1 [] ar = new Class1 [] { new Class1(1), new Class1(2), new Class1(3) };



2次元配列


int[,] a = new int[3,2]; int[,] a = new int[3,2]{ {1,1}, {1,1}, {1,1} };
画像データ
byte[,] image = new byte[128,128];



参照型の配列


POINT 参照型の配列の場合は, 配列自体の Instance の作成だけでなく, 要素を new した インスタンスをセットする必要がある。 各要素は参照型のため値は null となっている。 利用するには各要素ごとにさらにインスタンスをつくり、その値をセットしておく必要がある。 要素の数が10個なら、配列自身と要素を合わせて、11回のnewをする。
{ // インスタンスを作成。 string [] ar = new string[10]; for( int i=0; i<10; i++ ) { // 実行時に null を参照したというエラーになる //Console.WriteLine( ar[i].Length ); } for( int i=0; i<10; i++ ) { ar[i] = (i*2).ToString(); } for( int i=0; i<10; i++ ) { Console.WriteLine( ar[i].Length ); } }



初期化


 配列を宣言する際に、決まりきった値をあらかじめ決め打ちで入れてしまいたい場合がある。 また配列を作成時に 初期化を設定できる。
{ // 要素初期化つきで宣言. int [] ar1 = new int [4] { 0, 1, 2, 3 }; int [] ar2 = new int [] { 0, 1, 2, 3 }; // 省略系もある。 int [] ar3 = { 0, 1, 2, 3 }; for( int i=0; i<4; i++ ) { Console.WriteLine( "{0},{1},{2}", ar1[i], ar2[i], ar3[i] ); } }



ソート


POINT static System.Array.Sort() を利用してソートできる。 ソートするときの比較条件を指定する場合は, IComparable.CompareTo() を実装する。 IComparable インターフェイスを通じて、CompareTo メソッドが呼ばれる。  CompareTo メソッドは、インスタンス自身と引数のインスタンスを比較して その結果として、整数型の値を返す。 返値は、引数インスタンスよりも小さいときは、負の値、同じなら0、大きければ正の値を返すのがルール。
{ // Sort の条件は IComparable を実装することで実現できる. class Item : IComparable { public string name; public int price; public Item( string name, int price ) { this.name = name; this.price = price; } // 比較する必要な Interface // ここでは値段で比較. public int CompareTo( object obj ) { return price - ((Item)obj).price; } } class Test { static void Main(string[] args) { Item [] ar = { new Item("チョコ",50), new Item("煎餅",200), new Item("飴",10), new Item("ポテチ",100) }; // Itemクラスのインスタンスをソートする Array.Sort( ar ); foreach( Item it in ar ) { Console.WriteLine("{0},{1}",it.name,it.price); } } }



バイナリ・サーチ


POINT System.Array クラスには ソートだけでなくバイナリ・サーチも利用できる。
{ int [] ar = { 4,9,3,6,1,0 }; Array.Sort( ar ); foreach( int n in ar ) { Console.WriteLine( n ); } // Array.BinarySearch() で検索可能 int index = Array.BinarySearch( ar, 3 ); Console.WriteLine( "index of 3 is {0}", index ); }
値が“3”である要素のインデックスが“2”であることが分かる。 POINT Array.BinarySearch() を利用することで, BinarySearch を利用できる。 ただしソートすみである必要がある. POINT  配列型はれっきとしたデータ型なので、メソッドの引数に使ったり、 メソッドの戻り値として使ったりできる。 配列型は要素数を限定しないため、大きさの決まっていない配列を受け渡すことができる。
{ class Class1 { static public int [] makeArray( bool select ) { if( select ) { int [] ar = { 0,1,2,3 }; return ar; } else { int [] ar = { 0,1 }; // 配列型をかえす. return ar; } } // 配列型をうけとる. // 要素が何個の配列でも受け取ることができる。 static public void dumpArray( int [] ar ) { foreach( int n in ar ) { Console.WriteLine( n ); } } static void Main(string[] args) { int [] ar = makeArray(false); dumpArray( ar ); Console.WriteLine(); // 配列変数( 参照 )を再度代入することも可能. // 29 の 配列 Instance は参照がなくなるので, 消えることになる. ar = makeArray(true); dumpArray( ar ); } } }
要素数に関係なく、配列を受け渡しできる。 POINT 配列変数への代入は, 配列 Instance を再利用しないで, 新規に作成される. 各要素の表示にforeach文を使用すれば、要素の個数を調べる必要はない。 int []が指定されていることから分かるとおり、 このメソッドは、整数の配列を返す。 要素数に関係なく、戻値として渡すことができる。 WARNING 配列変数への代入は、配列の再利用にはならず、 別個の配列インスタンスが生成される。


参照型配列の初期化


POINT 参照型の配列も初期化できる
{ class Class1 { private int n; public Class1( int param ) { this.n = param; } static void Main(string[] args) { for( int i=0; i<3; i++ ) { Console.WriteLine( ar[i].n ); } } } }
配列の要素として Class1 のインスタンスを設定している。 配列作成時にClass1のコンストラクタに渡した値が順に表示される。 POINT 初期化リストの中に Class1クラスのインスタンスを作成するnewを書き込んでいること。 配列のメソッド POINT 配列型は クラスであり, System.Array から継承されたもの Array の Method はすべて使用できる。 配列変数は、一種のインスタンスである。 システムに標準で含まれる System.Array クラスから継承されたものであり、 このクラスが公開するメソッドなどはすべて利用できる。
{ { // int [] ar = { 0, 1, 2, 3, 4 }; // Array.Method を利用可能である. for( int i=ar.GetLowerBound(0); i<=ar.GetUpperBound(0); i++ ) { Console.WriteLine( ar[i] ); } }
配列の下限から上限までの各要素の値が順に表示される。 GetLowerBoundメソッドは、配列の添え字の下限を返す。 GetUpperBoundメソッドは、添え字の上限の値を返す。 それぞれ、引数の0というのは、最初の次元を意味する。 1次元配列の場合は常にゼロだが、2次元以上になると、何次元目の上限、下限の値を得るか示すために、 0から次元数マイナス1の値のいずれかを指定する。 配列はただ配列なのではなく それ自身がインスタンスとしての側面も持つことを忘れてはならない。


foreach


 foreach 文の効能により ループをまわりながら 配列の要素が1つずつ変数nに代入される。 これにより 配列の添字の範囲を意識することなく、すべての要素にアクセスできる。 WARNING   foreach文でアクセスした場合、配列の内容を書き換えられないこと。 この場合、変数nの値を書き換えても、変数nが変わるだけであって 配列の要素の値が変わることにはならない。


文字配列と文字列の相互変換


C#では、いかに容易に文字配列と文字列の間の相互変換ができるかを示す。
{ class Class1 { static void Main(string[] args) { // char の配列 char [] ar1 = { 'A', 'B', 'C' }; foreach( char c in ar1 ) { Console.WriteLine(c); } // string 型 Ctor に char[] を指定 string s = new string( ar1 ); Console.WriteLine(s); // char の配列型 char [] ar2 = s.ToCharArray(); foreach( char c in ar2 ) { Console.WriteLine(c); } } } }
POINT char[], string の相互変換は簡単. char[] -> string : string( char [] ); string -> char[] : string.ToCharArray(); 最初に文字の配列の各要素が表示され、次に文字列に変換されたものが表示され、 最後に再び配列に戻されたものが表示されている。 string(System.String) のコンストラクタに文字(char)の配列を指定すれば、 その内容を文字列として生成する。 文字列に ToCharArray メソッドを使うと、戻り値として、文字の配列が返ってくる。  C#では、C/C++と違って、文字の配列と文字列はまったく別のものになる。 必要ならば相互に変換することは簡単にできる。 まとめ  C#の配列は、配列自身が1つのインスタンスである