Array.IndexOf() / Array.Copy()
| 対応: | C# 1.0(2002) |
|---|
配列の中から指定した値を検索する『Array.IndexOf()』と、配列の内容を別の配列にコピーする『Array.Copy()』メソッドです。
構文
// 配列の中で value が最初に現れるインデックスを返します。見つからない場合は -1 を返します。 Array.IndexOf(T[] array, T value) // array の sourceIndex から length 個の要素を destinationArray の destinationIndex にコピーします。 Array.Copy(T[] sourceArray, int sourceIndex, T[] destinationArray, int destinationIndex, int length) // array の先頭から length 個の要素を destinationArray の先頭にコピーします。 Array.Copy(T[] sourceArray, T[] destinationArray, int length)
メソッド一覧
| メソッド | 概要 |
|---|---|
| Array.IndexOf(T[] array, T value) | 配列の中で value と一致する最初の要素のインデックスを返します。見つからない場合は -1 を返します。 |
| Array.IndexOf(T[] array, T value, int startIndex) | startIndex から検索を開始し、最初に一致した要素のインデックスを返します。 |
| Array.Copy(Array src, Array dst, int length) | src の先頭から length 個の要素を dst の先頭にコピーします。 |
| Array.Copy(Array src, int srcIdx, Array dst, int dstIdx, int length) | src の srcIdx から length 個の要素を dst の dstIdx にコピーします。 |
サンプルコード
Array.IndexOf() で要素の位置を検索します。見つからない場合は -1 が返ります。
Program.cs
using System;
string[] languages = { "C#", "Java", "Python", "Go", "Rust" };
int index = Array.IndexOf(languages, "Python");
Console.WriteLine(index); // 2
int notFound = Array.IndexOf(languages, "Swift");
Console.WriteLine(notFound); // -1
string target = "Java";
if (Array.IndexOf(languages, target) != -1)
{
Console.WriteLine($"{target} は配列内に存在します。");
}
コンパイルして実行すると次のようになります。
dotnet run 2 -1 Java は配列内に存在します。
Array.Copy() で配列をコピーする
Array.Copy() は配列の内容を別の配列にコピーします。コピー先の要素を変更しても元の配列には影響しません(値型の場合)。
CopySample.cs
using System;
int[] source = { 10, 20, 30, 40, 50 };
int[] dest = new int[source.Length];
Array.Copy(source, dest, source.Length);
dest[0] = 999;
Console.WriteLine(source[0]); // 10(元の配列は変更されていない)
Console.WriteLine(dest[0]); // 999
// 部分コピー(インデックス1から3要素をコピー先のインデックス0へ)
int[] partial = new int[3];
Array.Copy(source, 1, partial, 0, 3);
Console.WriteLine(string.Join(", ", partial)); // 20, 30, 40
コンパイルして実行すると次のようになります。
dotnet run 10 999 20, 30, 40
startIndex を指定した検索
Array.IndexOf() の第3引数 startIndex を使うと、指定した位置以降から検索を開始します。同じ値が複数存在する配列で次の出現位置を探すときに使います。
SearchSample.cs
using System;
string[] members = { "桐生一馬", "真島吾朗", "桐生一馬", "秋山駿" };
int first = Array.IndexOf(members, "桐生一馬");
Console.WriteLine(first); // 0
int second = Array.IndexOf(members, "桐生一馬", first + 1);
Console.WriteLine(second); // 2
// すべての出現位置を列挙する
int pos = 0;
while ((pos = Array.IndexOf(members, "桐生一馬", pos)) != -1)
{
Console.WriteLine($"インデックス {pos} に見つかりました。");
pos++;
}
コンパイルして実行すると次のようになります。
dotnet run 0 2 インデックス 0 に見つかりました。 インデックス 2 に見つかりました。
よくあるミス
よくあるミス: Array.Copy() は参照型をシャローコピーする
Array.Copy() は参照型の要素をシャローコピー(浅いコピー)します。クラスのインスタンスなどを含む配列をコピーした場合、コピー先の要素は元の配列と同じオブジェクトを参照します。一方を変更するともう一方にも影響します。
using System;
class Character
{
public string Name;
public int Level;
}
Character a = new Character { Name = "桐生一馬", Level = 50 };
Character[] original = { a };
Character[] copy = new Character[1];
Array.Copy(original, copy, 1);
copy[0].Level = 99; // コピー先を変更する
Console.WriteLine(original[0].Level); // 99(元も変わってしまう)
修正後は次の通りです。
dotnet run 99
値型(int, double, struct など)の配列では この問題は発生しません。参照型を深くコピーしたい場合は、各要素を個別に new でインスタンス化してコピーするか、シリアライズ/デシリアライズの手法を使います。
概要
Array.Copy() はシャローコピー(浅いコピー)を行います。参照型の要素(クラスのインスタンスなど)を含む配列の場合、コピー先の要素は元の配列と同じオブジェクトを参照します。値型(int, double など)の配列では問題ありません。
配列の内容を確認したい場合は、事前に『Length / Array.Resize()』で要素数を確認し、インデックス範囲内でアクセスしてください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。