如何实现ICollection.CopyTo方法?

20 浏览
0 Comments

如何实现ICollection.CopyTo方法?

我正在编写一个实现ICollectionICollection接口的类。\nMSDN说它们有一些不同。ICollection.CopyTo方法接受一个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);
}

0
0 Comments

在实现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.");
}

0
0 Comments

问题的出现原因:

在实现ICollection.CopyTo方法时,有四种可能性:

1. 它与ICollection的行为相同。

2. 它会因为与ICollection相同的原因而失败。

3. 它会因为秩不匹配而失败。

4. 它会因为类型不匹配而失败。

解决方法:

我们可以通过调用ICollection.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)this).CopyTo(ppArray, index);
}

如果你愿意的话,你可以在ppArray为null的情况下测试array.Rank == 1,并相应地更改错误消息。

(顺便问一下,为什么你要显式实现ICollection.CopyTo?它足够有用,以至于值得显式实现,这样人们就不必将其全部转换了。)

非常感谢,这似乎是一个完美的解决方案。出于某种原因,我没有考虑到将其转换为T[]。我也会采纳你的建议,不再显式实现。

如果你这样做,你可以将相当丑陋的((ICollection)this).CopyTo(ppArray, index)改为CopyTo(ppArray, index)。

0