配列エラーの範囲外の索引を回避するためのアレイをパッケージする方法
-
13-12-2019 - |
質問
私はそれを照会するときに私のリストに少なくとも183のアイテムを持つことが期待されていますが、私の抽出からの結果は183より低い項目の結果になります。私の現在の修正は、カウントが小さい場合にはアレイを埋めます。183.
if (extractArray.Count() < 183) {
int arraysize= extractArray.Count();
var tempArr = new String[183 - arraysize];
List<string> itemsList = extractArray.ToList<string>();
itemsList.AddRange(tempArr);
var values = itemsList.ToArray();
//-- Process the new array that is now at least 183 in length
}
.
しかし、私の解決策は最高ではないようです。抽出物が起こっているときはいつでも少なくとも183のアイテムを得るのを助けることができる他の解決策を理解するでしょう。
他のヒント
おそらく他人の提案に従い、リストを使用します。パフォーマンスを追加するために "Capacity"コンストラクターを使用してください:
var list = new List<string>(183);
.
それでは、新しい配列を取得するときはいつでも、これを行うために使用する値を使用してください。
list.Clear();
list.AddRange(array);
// logically, you can do this without the if, but it saves an object allocation when the array is full
if (array.Length < 183)
list.AddRange(Enumerable.Repeat(" ", 183 - array.Length));
.
このように、リストは常に同じ内部配列を再利用し、割り当てとGC圧力を低減しています。
または、拡張方法を使用することができます。
public static class ArrayExtensions
{
public static T ElementOrDefault<T>(this T[] array, int index)
{
return ElementOrDefault(array, index, default(T));
}
public static T ElementOrDefault<T>(this T[] array, int index, T defaultValue)
{
return index < array.Length ? array[index] : defaultValue;
}
}
.
そのようなコードをコード:
items.Zero = array[0];
items.One = array[1];
//...
.
これになる:
items.Zero = array.ElementOrDefault(0);
items.One = array.ElementOrDefault(1);
//...
.
最後に、これは私がこの回答を書いたスタートを始めたかなり面倒なアイデアです.IList実装に配列を183のインデックスを持つことが保証されている(簡潔にするためのインターフェースメンバー実装の大部分を省略しました):
class ConstantSizeReadOnlyArrayWrapper<T> : IList<T>
{
private readonly T[] _array;
private readonly int _constantSize;
private readonly T _padValue;
public ConstantSizeReadOnlyArrayWrapper(T[] array, int constantSize, T padValue)
{
//parameter validation omitted for brevity
_array = array;
_constantSize = constantSize;
_padValue = padValue;
}
private int MissingItemCount
{
get { return _constantSize - _array.Length; }
}
public IEnumerator<T> GetEnumerator()
{
//maybe you don't need to implement this, or maybe just returning _array.GetEnumerator() would suffice.
return _array.Concat(Enumerable.Repeat(_padValue, MissingItemCount)).GetEnumerator();
}
public int Count
{
get { return _constantSize; }
}
public bool IsReadOnly
{
get { return true; }
}
public int IndexOf(T item)
{
var arrayIndex = Array.IndexOf(_array, item);
if (arrayIndex < 0 && item.Equals(_padValue))
return _array.Length;
return arrayIndex;
}
public T this[int index]
{
get
{
if (index < 0 || index >= _constantSize)
throw new IndexOutOfRangeException();
return index < _array.Length ? _array[index] : _padValue;
}
set { throw new NotSupportedException(); }
}
}
.
ack。
あなたは183の索引があることを確実にする必要があると述べたので、そうでなければパッドを埋める必要があると述べたので、配列の代わりにリストを使用することをお勧めします。あなたは何かをすることができます:
while (extractList.Count < 183)
{
extractList.Add(" "); // just add a space
}
.
あなたが絶対に配列に戻る必要があるならば、あなたは似たものを使うことができます。
私はこの解決策を推薦するだろうと言うことができませんが、私はそれを投稿するのをやめさせません!彼らがそれを認めるのが好きかどうか、誰もがlinqソリューションを好む!
LINQを使用して、Xエレメントを持つ配列を指定して、y(caseの183の場合は183の場合)の要素がこのようなものです。
var items183exactly = extractArray.Length == 183 ? extractArray :
extractArray.Take(183)
.Concat(Enumerable.Repeat(string.Empty, Math.Max(0, 183 - extractArray.Length)))
.ToArray();
.
183未満の要素がある場合、アレイに空の文字列が埋め込まれます。183を超える要素がある場合、配列は切り捨てられます。正確に183個の要素がある場合、配列はそのまま使用されます。
これが効率的であると主張していない、または必然的に良い考えであることを主張していません。ただし、LINQ(YIPPEE!)を使用しています。