0

在 stackoverflow 上的另一个问题中,有人建议为数组编写扩展方法,但this IList<T>在扩展方法中使用了接口。我评论说它应该是一个数组,但他拒绝了。我测试了它,当然,他是对的...... :)

扩展方法:

public static void Fill<T>(this IList<T> array, T value)
{
    for(var i = 0; i < array.Count; i++) 
    {
        array[i] = value;
    }
}

测试代码:

[Test] 
public void Stackoverflow()
{
    int[] arr = new int[] { 1,2,3,4};
    arr.Fill(2);
    Assert.AreEqual(2, arr[0]);
    Assert.AreEqual(2, arr[1]);
    Assert.AreEqual(2, arr[2]);
    Assert.AreEqual(2, arr[3]);
}

一个array不是一个IList<T>。为什么这甚至可以编译?更别说,通过?!

4

4 回答 4

6

Array没有实现IList<T>,但T[]由于一些运行时魔法,它确实实现了。数组有点奇怪,因为它应该是通用的,但早于通用系统,因此使用了专门的 hack。

于 2013-02-17T09:00:05.300 回答
5

从 C# 4 规范的第 12.1.2 节:

一维数组T[]实现接口System.Collections.Generic.IList<T>及其基本接口。因此,存在从T[]toIList<T>及其基本接口的隐式转换。

值得注意的是,如果您创建一个矩形数组一维数组,其下界不是零,则不会实现IList<T>.

在 CLI 中,实际上有两个术语:向量数组。向量是一个下界为零的一维集合,并被 JIT 优化为可以返回。一个数组可以有多个维度和不同的下界,并且不需要进行彻底的优化。

T[]C# 中的A始终是向量。您不能将作为 CLI 数组的对象强制转换为T[]- 您最终会遇到如下异常:

Unhandled Exception: System.InvalidCastException: Unable to cast object of type
'System.String[*]' to type 'System.String[]'.
于 2013-02-17T09:02:14.580 回答
1

编辑:最初认为 OP 是在询问IList而不是IList<T>.

...因为数组实现IList

public abstract class Array : ICloneable, IList, ICollection, IEnumerable, IStructuralComparable, IStructuralEquatable
//                                        ^^^^^
于 2013-02-17T08:58:59.327 回答
1

在一个稍微相关的注释上:

不幸的是, T[] 有时会实现 IList<T> 。考虑以下代码:

int[] array = new int[10];
IList<int> list = array; // Compiles
list.Add(1);             // Runtime error. Ew!

真的不是很好。

因此,在使用 IList<T> 而不是 T[] 之前需要仔细考虑。

于 2013-02-17T09:46:58.893 回答