3

配列の長さを宣言するか、アイテムをすぐに追加しない限り、C# 内で配列にオブジェクトを追加できないのはなぜですか? たとえば、私は単純にこれを行うことができませんでした

foreach(object item in array)
{
   array.Add(item)
}

リストを作成し、ループの後に配列に変換する必要があります。

方法を知りたくありません。なぜ配列は固​​定長であるのに、他のコレクションは固定長ではないのか (List、ListArray) の論理的な説明が必要です。

4

6 に答える 6

5

配列はサイズ変更できません。これがメモリの仕組みだからです。.NET でメモリ割り当てが正確にどのように機能するかを理解することは、SO の答えとしては少し難しいです。必要に応じて他の場所でそれについてすべて読むことができますが、1 つの側面は基本的にすべてのプラットフォームで普遍的です: 何かに割り当てられたメモリがある場合、その後の次のアドレスは、何か他のものの一部である可能性があります。

したがって、メモリの一部を拡張して、何も問題が発生しないことを祈ることはできません。拡張できることをテストし、拡張できない場合に備えてプラン B を用意する必要があります。そのプラン B は、新しいブロックを割り当てます。メモリに古いものをコピーし、古いブロックの割り当てを解除します。

何度も再割り当てとコピーを行うのを避けるために、新しいブロックを古いブロックの 2 倍の大きさにするのが一般的です。そのため、nアイテムを追加する場合は、再割り当てとコピーの回数だけを使用し、新しいアイテムを動的に成長するブロックに追加するための償却時間をO(log n)維持します。 O(1) までの配列。とても一定の時間、素晴らしい-そうではありません。再割り当てする必要がなかった場合よりもまだ時間がかかります。実際、成長を引き起こさないすべてのものでさえ、addまだ成長が必要でないことを確認するために少しオーバーヘッドがあります。

したがって、成長しない配列ははるかに単純で、少し高速で、メモリの浪費が少なくなります。そのため、C# (および Java や C++ などの他の多くの言語) では、成長可能な「配列のようなもの」を使用するか、成長不可能なものを使用するかを選択する必要があります。そこにはトレードオフがあり、これらの言語はユーザーに代わってその決定を行わないことを選択します。

于 2013-07-09T11:08:06.113 に答える
3

また、昔ながらの方法で for ループを使用することもできます。それはイテレータとコレクションの変更の問題を認識しておらず、その一時的なリストは必要ありません (かなり非効率的です)。

于 2013-07-09T10:27:06.707 に答える
1

実際、あなたの質問は明確ではないか、まったく意味がありません。既存の配列 (サイズは定義されているが、値は指定されていない) にデータを入力しようとしている場合は、次のようにすることができます。

var myArray = new string[5];

for(var i = 0; i < myArray.Length; i++)
{
  myArray[i] = "Some value here..."; 
}

ただし、配列自体に既存の項目を追加しても意味がありません。

注:Add()メソッドはListなどのために存在しますが、通常、「この要素をコレクションの最後に追加する」ことを意味します。

配列には変更できない定義済みの長さがあるため、それに追加することはできません-既存の要素のみを変更します。

于 2013-07-09T10:42:50.383 に答える