如何实现ICollection.CopyTo方法?
如何实现ICollection.CopyTo方法?
我正在编写一个实现ICollection
和ICollection
接口的类。\nMSDN说它们有一些不同。ICollection
方法接受一个T[]
参数,而ICollection.CopyTo
方法接受一个System.Array
参数。它们抛出的异常也有所不同。\n这是我对泛型方法的实现(我相信它是完全功能的):\n
void ICollection.CopyTo(PlcParameter[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException("array"); if (arrayIndex < 0) throw new ArgumentOutOfRangeException("arrayIndex"); if (array.Length - arrayIndex < Count) throw new ArgumentException("目标数组中的 arrayIndex 后没有足够的元素。"); for (int i = 0; i < Count; ++i) array[i + arrayIndex] = this[i]; }
\n然而,非泛型版本的方法让我有点困惑。首先,我如何检查以下异常条件?\n
\n源 ICollection 的类型不能自动转换为目标数组的类型。\n
\n其次,是否有一种方法可以利用现有的泛型实现以减少代码重复?\n这是我正在进行的工作的实现:\n
void ICollection.CopyTo(Array array, int index) { if (array == null) throw new ArgumentNullException("array"); if (index < 0) throw new ArgumentOutOfRangeException("arrayIndex"); if (array.Rank > 1) throw new ArgumentException("数组是多维的。"); if (array.Length - index < Count) throw new ArgumentException("目标数组中的 index 后没有足够的元素。"); for (int i = 0; i < Count; ++i) array.SetValue(this[i], i + index); }
在实现ICollection.CopyTo方法时,可能会遇到以下情况:
1. 类型完全匹配:调用泛型版本的CopyTo方法。
2. 数组是object[]类型:特别是当T是引用类型时,需要处理这种情况,因为在这种情况下,T[]可以转换为object[]。
3. 如果集合是字典类型,还可以处理KeyValuePair[]和DictionaryEntry[]数组。
因此,在一般情况下,可以使用以下实现方法:
void ICollection.CopyTo(Array array, int index) { if (array != null && array.Rank != 1) throw new ArgumentException("Only single dimensional arrays are supported for the requested action.", "array"); // 1. 调用泛型版本 T[] typedArray = array as T[]; if (typedArray != null) { CopyTo(typedArray, index); return; } // 2. object[] object[] objectArray = array as object[]; if (objectArray != null) { for (int i = 0; i < size; i++) { objectArray[index++] = GetElementAt(i); } } throw new ArgumentException("Target array type is not compatible with the type of items in the collection."); }
问题的出现原因:
在实现ICollection.CopyTo方法时,有四种可能性:
1. 它与ICollection
2. 它会因为与ICollection
3. 它会因为秩不匹配而失败。
4. 它会因为类型不匹配而失败。
解决方法:
我们可以通过调用ICollection
在这两种情况下,array as PlcParameter[]将给我们一个引用到数组,强类型化。
而在后两种情况下,它不会给我们强类型化的数组引用。
但是我们确实希望单独捕获array == null的情况:
void ICollection.CopyTo(Array array, int index) { if (array == null) throw new ArgumentNullException("array"); PlcParameter[] ppArray = array as PlcParameter[]; if (ppArray == null) throw new ArgumentException(); ((ICollection)this).CopyTo(ppArray, index); }
如果你愿意的话,你可以在ppArray为null的情况下测试array.Rank == 1,并相应地更改错误消息。
(顺便问一下,为什么你要显式实现ICollection
非常感谢,这似乎是一个完美的解决方案。出于某种原因,我没有考虑到将其转换为T[]。我也会采纳你的建议,不再显式实现。
如果你这样做,你可以将相当丑陋的((ICollection