在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>
。为什么这甚至编译?不过,通过?!
答案 0 :(得分:6)
Array
没有实现IList<T>
,但T[]
确实没有实现,这要归功于一些运行时魔术。数组有点奇怪,因为它应该是通用的,但是先于通用系统,因此使用专门的黑客。
答案 1 :(得分:5)
来自C#4规范的第12.1.2节:
一维数组
T[]
实现接口System.Collections.Generic.IList<T>
及其基接口。因此,存在从T[]
到IList<T>
及其基接口的隐式转换。
值得注意的是,如果你创建一个矩形数组或一个具有非零的下限的一维数组,那些不实现{{1} }。
在CLI中,实际上有两个术语: vector 和 array 。向量是一个下限为零的一维集合,并且被JIT优化为heck和back。数组可以具有多个维度和不同的下限,并且不需要进行彻底的优化。
C#中的IList<T>
总是一个向量。你不能将一个CLI数组的对象强制转换为T[]
- 最终会出现这样的异常:
T[]
答案 2 :(得分:1)
编辑:最初认为OP询问的是IList
而不是IList<T>
。
...因为数组实现IList
:
public abstract class Array : ICloneable, IList, ICollection, IEnumerable, IStructuralComparable, IStructuralEquatable
// ^^^^^
答案 3 :(得分:1)
稍微相关的说明:
T []实现IList&lt; T&gt;非常不幸。有时。请考虑以下代码:
int[] array = new int[10];
IList<int> list = array; // Compiles
list.Add(1); // Runtime error. Ew!
真的不太好。
出于这个原因,在使用IList&lt; T&gt;之前需要仔细考虑。而不是T []。