【ソースコード有】C#の配列を扱いやすくするArrayクラスの使い方
C#のArrayクラスの特徴や使い方について、具体的なサンプルコードとともに説明していきます。
C#のArrayクラスの特徴や使い方について、具体的なサンプルコードとともに説明していきます。
スキルアップ
2023/01/26 UP
- SE資格・スキル
- プログラミング
- システムエンジニア
配列とは、同じ型の値を連続的に配置したデータ構造のことです。さまざまなプログラミング言語に広く取り入れられており、もちろんC#でも使えます。
C#の配列には、標準で使える便利な機能が豊富です。しかし、そうした機能がArrayクラスによって提供されていることは、あまり知られていないかもしれません。そこで今回は、C#のArrayクラスの特徴や使い方について、具体的なサンプルコードとともに説明していきます。
なお、C#を基本から押さえたい場合は、こちらの記事からチェックしてみてください。
【C#入門】プログラムの基本的な文法や書き方をサンプル付きで解説
C#のArrayクラスとは
Arrayクラスには、C#の配列が「いつの間にか」備えている機能がまとめられています。まずは、その仕組みと特徴について理解しましょう。
C#の配列はArrayクラスのオブジェクト
C#においては、配列は単なるデータ領域ではありません。C#のプログラム中に定義されたあらゆる配列は、Arrayクラスを親とするクラスのオブジェクトです。そのため、すべての配列は自動的にArrayクラスに属しており、その機能を備えています。
配列を使ううえで、普段からArrayクラスの存在を意識することは少ないかもしれません。しかし、ひとたびArrayクラスに注目してみると、実用的な機能を豊富に備えていることがわかります。
例えば、「配列の要素数はLengthで取得できる」と覚えている人もいるでしょう。実はこれも、Arrayクラスが備えているプロパティの一つです。
Arrayクラスで強化される配列の機能
Arrayクラスを活用すると、配列に対してさまざまな操作ができるようになります。例えば、次のような機能を利用可能です。
・配列から配列へ、要素をまとめてコピーする
・配列の要素から、指定した条件を満たすものを検索する
・配列の要素を、指定した順序で並び替える
これらと同様の機能は、Arrayクラスに頼らずとも自力で作れるかもしれません。しかし、Arrayクラスの既存機能のみで可能だと知らずにいるのは、もったいないことだといえます。
このあと、それぞれの機能の具体的な使い方について説明していくので、ぜひ役立ててください。
C#における配列の基本操作
Arrayクラスを十分に活用するための基礎として、まずはC#における配列の基本的な操作方法について確認しておきましょう。
配列の作成と初期化
C#では、配列は次のような形式で作成することが多いでしょう。
var myArray1 = new[] { 1, 2, 3, 4, 5, 6, 7 }; var myArray2 = new[] { "a", "b", "c", "d", "e", "f", "g" };
1行目は整数値の配列、2行目は文字列の配列の例です。どちらもの配列も、作成と同時に初期値が与えられています。
C#ではあらゆる配列がArrayクラスに属するオブジェクトであるにも関わらず、ここにはArrayクラスに関する記述が一切ありません。配列をArrayクラスに割り当てる動作は、背後で自動的に行なわれるためです。
要素へのアクセスとループ
配列の要素を順番に処理したいときは、ループを使うことが多いでしょう。C#の配列はforeach文に対応しており、次のようにループを記述できます。
サンプルコード:
var myArray = new[] { "a", "b", "c" }; foreach (var item in myArray) { Console.WriteLine(item); }
実行結果:
a b c
この例では、要素が3つの配列を作成し、foreach文で処理しています。foreach文では要素を順番に取り出し、1つずつ処理することが可能です。
foreach文ではなく、次のようにfor文を用いてループする方法もあります。
サンプルコード:
var myArray = new[] { "a", "b", "c" }; for (var i=0; i<myArray.Length; i++) { Console.WriteLine("要素" + i + ":" + myArray[i]); }
実行結果:
要素0:a 要素1:b 要素2:c
この例でfor文がforeach文と異なっているのは、ループ変数(ここでは「i」)を用いている点です。これにより、配列の要素にインデックスでアクセスしています。
先に説明したように、for文とともに使用している「Length」は、実はArrayクラスのプロパティです。それ以外には、いずれのループにもArrayクラスの存在を強く意識させるような記述はありません。
C#のArrayクラスによる配列の操作
ただ配列を作成したり、それをループで処理したりするだけでは、Arrayクラスならではの記述はなかなか出てこないことがわかりました。Arrayクラスにどのような機能があるのかを知り、積極的に使おうとしなければ、その便利さに気付くことは難しいといえるでしょう。
ここからは、Arrayクラスの基本的な使い方について、具体例を挙げながら説明していきます。
配列のクリア(Clear/Fill)
「Clear()」メソッドを使うと、配列の要素をクリアすることができます。次のプログラムで、具体的な動作を確認してみましょう。
サンプルコード:
var myArray = new[] { "a", "b", "c" }; Array.Clear(myArray,0,myArray.Length); Console.WriteLine("配列の要素数:" + myArray.Length); for (var i = 0; i < myArray.Length; i++) { Console.WriteLine("要素" + i + ":" + myArray[i]); }
実行結果:
配列の要素数:3 要素0: 要素1: 要素2:
要素が3つの配列を作成したあと、「Clear()」メソッドを呼び出しました。その直後に配列の要素数を取得すると、3のままになっています。また、ループで各要素を取り出して表示した結果から、初期値が消えていることもわかるでしょう。
このような結果になるのは、配列を「クリアする」と言っても、「Clear()」メソッドは配列そのものを空にするわけではないためです。要素数はそのままで、各要素をリセットするような動作をします。
もう1つ、別のクリア方法も紹介しましょう。
サンプルコード:
var myArray = new[] { "a", "b", "c" }; Array.Fill(myArray, "x"); Console.WriteLine("配列の要素数:" + myArray.Length); for (var i = 0; i < myArray.Length; i++) { Console.WriteLine("要素" + i + ":" + myArray[i]); }
実行結果:
配列の要素数:3 要素0:x 要素1:x 要素2:x
この例では「Clear()」メソッドの代わりに、「Fill()」メソッドを使用しました。「Fill()」メソッドは、指定の値で配列を「埋める」ような動作をします。これにより、明確に特定の値で各要素をクリアすることが可能です。
要素のコピー(Copy/CopyTo)
「CopyTo()」は、配列間で要素をコピーするメソッドです。次のようにコピー先の配列とインデックスを指定すれば、すべての要素がコピーされます。
サンプルコード:
var myArray1 = new[] { "a", "b", "c" }; var myArray2 = new[] { "one", "two", "three", "four", "five" }; myArray1.CopyTo(myArray2, 1); foreach (var item in myArray2) { Console.WriteLine(item); }
実行結果:
one a b c five
コピー先の配列に、コピー元の配列の内容がすべて埋め込まれたことがわかります。
しかし、配列内の一部の要素のみをコピーしたい場合もあるでしょう。それには、「Copy()」メソッドを使います。
「Copy()」メソッドに指定する引数は、次の5つです。
・コピー元の配列
・コピー元の配列の、コピーを開始するインデックス
・コピー先の配列
・コピー先の配列の、コピーを開始するインデックス
・コピーする要素数
どのように動作するのか、具体例で確認しておきましょう。
サンプルコード:
var myArray1 = new[] { "a", "b", "c" }; var myArray2 = new[] { "one", "two", "three", "four", "five" }; Array.Copy(myArray1, 1, myArray2, 1, 2); foreach (var item in myArray2) { Console.WriteLine(item); }
実行結果:
one b c four five
要素の存在確認(Contains/IndexOf)
「Contains()」または「IndexOf()」メソッドを使えば、配列に特定の要素が含まれるかどうかを調べることができます。
まずは、「Contains()」メソッドの使い方から確認しましょう。なお「Contains()」メソッドを使用する場合、LINQを使用するかIListを使用することになりますが、ここではLINQを使った方法を説明します。
まずはusingでこちらを指定してください。
using System.Linq;
サンプルコード:
var myArray = new[] { "one", "two", "three", "four", "five" }; if (myArray.Contains("two")) { Console.WriteLine("見つかりました。"); } else { Console.WriteLine("見つかりませんでした。"); }
実行結果:
見つかりました。
「Contains()」メソッドは、指定した値が存在する場合に「true」を返します。値の有無によって処理を分岐させたい場合に便利でしょう。
次は、「IndexOf()」メソッドの使い方を示します。
サンプルコード:
var myArray = new[] { "one", "two", "three", "four", "five" }; var index = Array.IndexOf(myArray, "two"); if (index != -1) { myArray[index] += "(見つかりました)"; } foreach (var item in myArray) { Console.WriteLine(item); }
実行結果:
one two(見つかりました) three four five
存在を確認したい値を指定する点は「Contains()」メソッドと同じですが、「IndexOf()」メソッドは、指定した値をもつ要素のインデックスを返す点が異なります。配列から特定の値を見つけ出して、別の値で更新したい場合などに便利でしょう。
なお、このメソッドは値が存在しない場合に「-1」を返すため、上の例にあるif文のようなチェックが必要です。
要素の検索(FindIndex)
「IndexOf()」メソッドで特定の値を見つける方法を紹介しましたが、「FindIndex()」メソッドを使えば、より柔軟な検索が可能です。
「FindIndex()」メソッドでは、第1引数に検索対象の配列、第2引数には検索条件を指定します。検索条件とは、要素の値を1つ受け取って、次のどちらかを返す処理のことです。
・true:検索したい値である
・false:検索したい値ではない
以下のプログラムで、実際の動作を確認してみましょう。長さが5の文字列を「検索したい値」とする例です。
サンプルコード:
var myArray = new[] { "one", "two", "three", "four", "five" }; var index = Array.FindIndex(myArray, item => item.Length == 5); if (index != -1) { Console.WriteLine("見つかりました:" + myArray[index]); } else { Console.WriteLine("見つかりませんでした。"); }
実行結果:
見つかりました:three
「FindIndex()」に第2引数として渡している「item => item.Length == 5」の部分が、少し難しく感じたかもしれません。これは、要素の値を「item」として受け取り、その長さが5かどうかを判定する処理を表しています。実行結果を見ると、5文字の値である「three」を検索できたことがわかるでしょう。
要素の並べ替え(Sort)
「Sort()」メソッドを使うと、次の例のように要素を並べ替えることができます。
サンプルコード:
var myArray = new[] { "one", "two", "three", "four", "five" }; Array.Sort(myArray); foreach (var item in myArray) { Console.WriteLine(item); }
実行結果:
five four one three two
このメソッドは、要素を小さい順に並べます。上記の例では要素が文字列になっているため、文字コードが小さい順、つまりアルファベット順に並べ替えられたということです。
並び順を独自のルールで決めたい場合もあるでしょう。それには第2引数に、2つの値を受け取り、以下のいずれかを返す処理を指定します。
・負の値:1つ目の値のほうが小さい
・ゼロ:2つの値が等しい
・正の値:1つ目の値のほうが大きい
具体的な使い方は、次のとおりです。
サンプルコード:
var myArray = new[] { "one", "two", "three", "four", "five" }; Array.Sort(myArray, (left, right) => left.Length - right.Length); foreach (var item in myArray) { Console.WriteLine(item); }
実行結果:
one two four five three
第2引数の「(left, right) => left.Length - right.Length」が、並び順を決めるための処理になっているのがわかるでしょうか。ここでは2つの値を「left」および「right」として受け取り、それぞれの長さを比較しています。その結果、文字列の長さが短い要素から長い要素へと並び替えられました。
要素数の変更(Resize)
「Resize()」メソッドを使うと、内容を維持しながら配列の要素数を変更できます。配列そのもののサイズが変わるという点で、やや特殊なメソッドといえるでしょう。
具体的には、次のように使用します。
サンプルコード:
var myArray = new[] { "a", "b", "c" }; Console.WriteLine("リサイズ前の要素数:" + myArray.Length); Array.Resize(ref myArray, 5); Console.WriteLine("リサイズ後の要素数:" + myArray.Length); for (var i = 0; i < myArray.Length; i++) { Console.WriteLine("要素" + i + ":" + myArray[i]); }
実行結果:
リサイズ前の要素数:3 リサイズ後の要素数:5 要素0:a 要素1:b 要素2:c 要素3: 要素4:
実行結果から、要素数が増えても既存の値が消えていないことがわかるでしょう。
このメソッドは、指定された要素数の配列を新たに確保したうえで要素をコピーし、もとの配列を新しい配列で置き換えるという動作をしています。
C#の配列で要素の挿入や削除を行なうにはListクラスを
配列に対する要素の挿入や削除は、簡単にはできません。配列内の各要素は連続的に配置されているため、挿入・削除する要素以降の並びをずらす処理が、どうしても必要になるのです。
こうした処理は、Arrayクラスの「Resize()」や「Copy()」などのメソッドを組み合わせれば不可能ではありません。とはいえ、動的な配列の機能をもつクラスを活用するほうが現実的でしょう。
C#には、必要に応じて配列の要素数を増やせる「ArrayList」というクラスがあります。しかし、それよりも任意の型に対応し、パフォーマンスの面でも優れた「List」クラスを使うほうがおすすめです。
詳しくは、こちらの記事も参考にしてください。
【ソースコード有】C#でデータの一覧を扱うListクラスの使い方
C#のArrayクラスで配列を効率的に操作しよう
C#の配列は、Arrayクラスに属するオブジェクトです。そのため、Arrayクラスにより提供される豊富な機能を、あらゆる配列から利用できます。具体的には要素のコピーや存在確認、検索、並べ替えなどが可能です。
これらの機能について知り、積極的に利用していけば、自力で作らなければならない配列の処理を減らすことも可能でしょう。Arrayクラスの機能を活用して、プログラミングの効率化を目指してみてはいかがでしょうか。