-
03-07-2019 - |
質問
[MSDN:配列の使用ガイドライン]( http://msdn.microsoft.com/en-us/library/k2604h5s(VS.71).aspx):
配列値プロパティ
コードの非効率性を避けるために、コレクションを使用する必要があります。次のコード例では、myObjプロパティを呼び出すたびに配列のコピーが作成されます。その結果、次のループで配列の2n + 1コピーが作成されます。
[Visual Basic]
Dim i As Integer
For i = 0 To obj.myObj.Count - 1
DoSomething(obj.myObj(i))
Next i
[C#]
for (int i = 0; i < obj.myObj.Count; i++)
DoSomething(obj.myObj[i]);
myObj []からICollection myObjへの変更以外に、他に何をお勧めしますか?私の現在のアプリがメモリをリークしていることに気付きました:(
ありがとう;
編集:C#にref(安全は別として)参照を渡すように強制すると、パフォーマンスやメモリ使用量が向上しますか?
解決
いいえ、メモリをリークしているわけではありません-ガベージコレクタの動作を想像以上に難しくしているだけです。実際、MSDNの記事は少し誤解を招く可能性があります。プロパティが呼び出されるたびに新しいコレクションを作成した場合、配列と同じくらい(メモリに関して)悪いでしょう。おそらく、ほとんどのコレクション実装の通常のオーバーサイズが原因で、さらに悪いことになります。
メソッド/プロパティが機能することがわかっている場合は、いつでも呼び出し回数を最小限に抑えることができます。
var arr = obj.myObj; // var since I don't know the type!
for (int i = 0; i < arr.Length; i++) {
DoSomething(arr[i]);
}
さらに簡単に、 foreach
を使用します:
foreach(var value in obj.myObj) {
DoSomething(value);
}
両方のアプローチは、プロパティを1回だけ呼び出します。 2番目はIMOがより明確です。
その他の考え;メソッドと名付けてください!すなわち、 obj.SomeMethod()
-これは動作するという期待を設定し、望ましくない obj.Foo!= obj.Foo
(配列の場合)を回避します。
最後に、Eric Lippertには優れたこのテーマに関する記事。
他のヒント
いくつかの回答で言及されているReadOnlyCollectionを使用していない人へのヒントとして:
[C#]
class XY
{
private X[] array;
public ReadOnlyCollection<X> myObj
{
get
{
return Array.AsReadOnly(array);
}
}
}
これが役立つことを願っています。
コストのかかるプロパティがある場合(呼び出し時にコレクションを再作成するなど)、各呼び出しにコストが発生することを示すプロパティを文書化するか、値をプライベートフィールドとしてキャッシュします。高価なプロパティゲッターはメソッドとして記述する必要があります。 一般に、コレクションを配列ではなくIEnumerableとして公開し、消費者にforeach(または列挙子)の使用を強制します。
作成しない限り、配列のコピーは作成されません。ただし、オブジェクトがプライベートに所有する配列に単純に参照を渡すと、厄介な副作用が発生します。参照を受け取った人は、基本的に、所有者が制御できない方法で内容を変更するなど、配列で好きなことを自由に行うことができます。
配列への不正な干渉を防ぐ1つの方法は、コンテンツのコピーを返すことです。別の(少しだけ良い)は、読み取り専用のコレクションを返すことです。
それでも、これらのことを行う前に、あまりにも多くの情報を提供しようとしているかどうかを自問する必要があります。場合によっては(実際には、かなり頻繁に)、配列をプライベートに保ち、代わりにそれを所有するオブジェクトで動作するメソッドを提供する方が良いでしょう。
myobjは、明示的に作成しない限り、新しいアイテムを作成しません。メモリ使用量を増やすために、プライベートコレクション(リストまたは任意)を使用し、プライベートコレクションから指定された値を返すインデクサーを公開することをお勧めします