如何实现ICollection.CopyTo方法?

时间:2016-02-15 14:52:43

标签: c# .net

我正在编写一个实现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);
}

2 个答案:

答案 0 :(得分:4)

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

ICollection.CopyTo有四种可能性:

  1. 它的工作方式与ICollection<T>相同。
  2. 由于ICollection<T>失败的原因,它会失败。
  3. 由于排名不匹配而失败。
  4. 因类型不匹配而失败。
  5. 我们可以通过调用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);
    }
    

    如果您真的希望在array.Rank == 1为空的情况下测试ppArray,请相应地更改错误消息。

    (顺便说一句,为什么你明确地实现了ICollection<PlcParameter>.CopyTo?它可能对于明确地实现工作是有用的,所以人们不必强制转换所有它。)

答案 1 :(得分:2)

在非通用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.");
}