填充数组以避免索引超出数组错误范围的方法

当我查询它时,我希望在我的列表中至少有183个项目,但有时候我的提取结果导致项目数低于183.我的当前修复假定在计数小于183的情况下填充数组。

if (extractArray.Count() < 183) { int arraysize= extractArray.Count(); var tempArr = new String[183 - arraysize]; List itemsList = extractArray.ToList(); itemsList.AddRange(tempArr); var values = itemsList.ToArray(); //-- Process the new array that is now at least 183 in length } 

但似乎我的解决方案不是最好的。 我将不胜感激任何其他解决方案可以帮助确保每当提取物发生时我至少得到183个项目。

Array基类实现Resize方法

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

但是,请记住,resize对性能有问题,因此只有在出于某种原因需要数组时,此方法才有用。 如果可以切换到列表

而且,我想你在这里有一维的一维字符串数组,所以我使用Length属性来检查数组中的有效项目数。

我可能会关注他人的建议,并使用一个列表。 使用“capacity”构造函数可以提高性能:

 var list = new List(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(this T[] array, int index) { return ElementOrDefault(array, index, default(T)); } public static T ElementOrDefault(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 : IList { 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 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(); } } } 

确认。

既然你已经声明你需要确保有183个索引,并且你需要填充它,如果没有,我会建议使用List而不是数组。 你可以这样做:

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

如果你绝对必须回到arrays,你可以使用类似的东西。

我不能说我会推荐这个解决方案,但我不会让它阻止我发布它! 无论他们是否愿意承认,每个人都喜欢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(yippee!)而且很有趣。