避免数组索引超出数组界限错误的填充数组方法

8

当我查询列表时,我希望至少有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个项,我将不胜感激。


7
你有没有考虑只使用 List<string> 而不是数组? - PiousVenom
2
你是如何处理它的,以便导致索引越界错误?在这种情况下,使用foreach循环不起作用吗? - Dave Zych
我并没有通过for循环来传递它。我只是将结果数组中的183个项目分配给我的代码中的特定项目。 - Kobojunkie
@Kobojunkie:我会选择 List<>,因为根本不需要填充。它比数组更好,因为它可以动态地改变大小以适应所需的任何大小。 - PiousVenom
1
我们不知道 OP 要求一个 183 项数组的原因。无论是切换到 List<>,都不能满足这个要求。 - Steve
显示剩余6条评论
4个回答

8

数组基类实现了Resize方法。

if(extractArray.Length < 183)
    Array.Resize<string>(ref extractArray, 183);

然而,需要注意的是,重新调整大小会影响性能,因此仅在必要时使用此方法。如果可以切换到List,则更好。

我假设这里有一个字符串的一维数组,所以我使用Length属性来检查数组中有效项的数量。


8

我建议您按照其他人的建议,使用列表。 使用“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));

这样,列表始终在重复使用同一内部数组,减少了分配和垃圾回收的压力。
或者,您可以使用扩展方法:
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(); }
    }
}

确认。


2

如果您需要确保有183个索引,并且需要在没有时进行填充,我建议使用List而不是数组。您可以这样做:

while (extractList.Count < 183)
{
     extractList.Add(" "); // just add a space
}

如果您绝对必须返回到一个数组,可以使用类似的方法。

2

我不能说我会推荐这个解决方案,但我不会因此停止发布它!无论他们是否愿意承认,每个人都喜欢Linq解决方案!

使用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(耶!)并且很有趣。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接