Способ прокладывать массив, чтобы избежать индекса вне границ ошибки массива
-
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 предметов, когда экстракт происходит, пожалуйста.
Решение
Базовый класс массива реализует Изменение изменений P >.
if(extractArray.Length < 183)
Array.Resize<string>(ref extractArray, 183);
.
Однако имейте в виду, что изменение изменений проблематично для производительности, поэтому этот метод полезен только в том случае, если вам требуется массив по какой-то причине.Если вы можете переключиться в список
И, я предполагаю, что у вас есть неодимерный массив строк здесь, поэтому я использую свойство длины для проверки эффективного количества элементов в массиве.
Другие советы
Я, наверное, следил за другими предложениями и использую список.Используйте конструктор «Емкость» для добавленной производительности:
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
}
.
Если вы абсолютно должны вернуться к массиву, вы можете использовать что-то похожее.
Я не могу сказать, что я бы порекомендовал это решение, но я не позволю этому останавливать меня от публикации!Хотеят ли они признать это или нет, все лайки BINQ Solutions!
Использование LINQ, учитывая массив с элементами x в нем, вы можете генерировать массив с именно y (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!) И это весело.