C# 如何实现ICollection.CopyTo方法?

C# 如何实现ICollection.CopyTo方法?,c#,.net,C#,.net,我正在编写一个实现ICollection和ICollection接口的类 MSDN说这些有点不同。接受T[]参数,而接受System.Array参数。抛出的异常之间也有区别 下面是我对泛型方法的实现(我相信它功能齐全): void ICollection.CopyTo(PlcParameter[]数组,int-arrayIndex) { if(数组==null) 抛出新的ArgumentNullException(“数组”); 如果(数组索引

我正在编写一个实现
ICollection
ICollection
接口的类

MSDN说这些有点不同。接受
T[]
参数,而接受
System.Array
参数。抛出的异常之间也有区别

下面是我对泛型方法的实现(我相信它功能齐全):

void ICollection.CopyTo(PlcParameter[]数组,int-arrayIndex)
{
if(数组==null)
抛出新的ArgumentNullException(“数组”);
如果(数组索引<0)
抛出新ArgumentOutOfRangeException(“arrayIndex”);
if(array.Length-arrayIndex
然而,该方法的非泛型版本让我有点困惑。首先,如何检查以下异常情况

无法将源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);
}
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.");
}
void ICollection.CopyTo(数组,int索引)
{
if(数组==null)
抛出新的ArgumentNullException(“数组”);
如果(指数<0)
抛出新ArgumentOutOfRangeException(“arrayIndex”);
如果(array.Rank>1)
抛出新ArgumentException(“数组是多维的”);
if(array.Length-索引<计数)
抛出新ArgumentException(“目标数组中索引后的元素不足”);
对于(int i=0;i
您已经完成了实现
ICollection.CopyTo
的大部分工作

ICollection.CopyTo有四种可能性:

  • 它的工作原理与
    ICollection
    相同
  • 它将失败,原因是
    i收集
    将失败
  • 由于秩不匹配,它将失败
  • 由于类型不匹配,它将失败
  • 我们可以通过调用
    ICollection.CopyTo
    来处理前两个问题

    在这些情况下,
    数组作为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);
    }
    
    void ICollection.CopyTo(数组,int索引)
    {
    if(数组==null)
    抛出新的ArgumentNullException(“数组”);
    PlcParameter[]ppArray=数组作为PlcParameter[];
    if(ppArray==null)
    抛出新ArgumentException();
    (ICollection)this.CopyTo(ppArray,index);
    }
    
    如果确实需要,可以在
    pArray
    为空的情况下测试
    array.Rank==1
    ,并相应地更改错误消息


    (顺便说一句,为什么要显式实现ICollection.CopyTo?
    ?显式实现work很可能很有用,这样人们就不必对它进行强制转换。)

    在非通用的
    CopyTo
    中,可能会发生以下情况:

    • 类型实际匹配:调用泛型版本
    • 数组是
      object[]
      :也处理这个数组,特别是当
      T
      是引用类型时,因为在这种情况下
      T[]
      可以强制转换为
      object[]
    • 如果您的集合是一个字典,那么您也可以处理
      KeyValuePair[]
      DictionaryEntry[]
      数组
    因此,在一般情况下,您应该使用以下实现:

    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);
    }
    
    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.");
    }
    
    void ICollection.CopyTo(数组,int索引)
    {
    if(array!=null&&array.Rank!=1)
    抛出新ArgumentException(“请求的操作只支持一维数组。”,“数组”);
    //1.调用通用版本
    T[]类型Darray=数组为T[];
    if(typedArray!=null)
    {
    CopyTo(typedArray,index);
    返回;
    }
    //2.对象[]
    object[]objectArray=作为对象[]的数组;
    if(objectArray!=null)
    {
    对于(int i=0;i
    Well
    SetValue
    肯定会为您抛出一个强制转换异常。您能否通过派生来实现类以节省工作?它为您实现了
    CopyTo()
    。看看这个问题-这里有一个集合,它是泛型的,基本上用扩展点包装了一个列表。它专门用于编写自定义泛型集合。@HansPassant假设底层实现是一个数组,但可能不是。非常感谢,这似乎是一个完美的解决方案。出于某种原因,我没有想到要投到
    t[]
    。我还将接受您关于不显式实现的建议。如果您这样做,那么您可以将相当难看的
    ((ICollection)this.CopyTo(ppArray,index)
    更改为
    CopyTo(ppArray,index)