如何实现ICollection.CopyTo方法

本文关键字:ICollection CopyTo 方法 实现 何实现 | 更新日期: 2023-09-27 18:34:43

我正在编写一个实现ICollection<T>ICollection接口的类。

MSDN表示这些有点不同。 ICollection<T>.CopyTo接受T[]论点,而ICollection.CopyTo接受System.Array论点。引发的异常之间也存在差异。

这是我对通用方法的实现(我相信它是功能齐全的(:

void ICollection<PlcParameter>.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("Not enough elements after arrayIndex in the destination array.");
    for (int i = 0; i < Count; ++i)
        array[i + arrayIndex] = this[i];
}

但是,该方法的非通用版本让我有点困惑。首先,如何检查以下异常情况

源 ICollection 的类型不能自动强制转换为目标阵列的类型。

其次,有没有办法利用现有的泛型实现来减少代码重复?

这是我正在进行的实施:

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("array is multidimensional.");
    if (array.Length - index < Count)
        throw new ArgumentException("Not enough elements after index in the destination array.");
    for (int i = 0; i < Count; ++i)
        array.SetValue(this[i], i + index);
}

如何实现ICollection.CopyTo方法

您已经完成了实现ICollection<T>.CopyTo的大部分工作。

ICollection.CopyTo有四种可能性:

  1. 它将与ICollection<T>相同
  2. 它将失败,原因ICollection<T>会失败。
  3. 它将由于等级不匹配而失败。
  4. 它将由于类型不匹配而失败。

我们可以通过调用 ICollection<T>.CopyTo 来处理前两个。

在每种情况下,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<PlcParameter>)this).CopyTo(ppArray, index);
}

如果您真的想要,您可以在ppArray为 null 的情况下测试 array.Rank == 1,并相应地更改错误消息。

(顺便说一句,你为什么要显式实现ICollection<PlcParameter>.CopyTo?明确实现工作可能足够有用,所以人们不必全部投射到它。

在非泛型CopyTo中,可能会发生以下情况:

  • 类型实际匹配:调用泛型版本
  • 数组是object[]:也处理这个,特别是如果T是引用类型,因为在这种情况下T[]可以转换为object[]
  • 如果您的集合是字典,则还可以处理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. call the generic version
    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.");
}