[英]How to simplify the initialization of List<List<Int32>> as IEnumerable<IEnumerable<Int32>>?
我正在做以下集合初始化:
Int32[,] v1 = new Int32[2, 2] { { 1, 2 }, { 3, 4 } };
IEnumerable<IEnumerable<Int32>> v2 = new List<List<Int32>> { { 2, 3 }, { 3, 4 } };
在第二行我得到错误:
No overload for method 'Add' takes 2 arguments
有没有办法使用最新的 C# 版本来创建IEnumerable<IEnumerable<Int32>>
而不为主集合中的每个项目添加new List<Int32>
?
IEnumerable<IEnumerable<Int32>> v2 = new List<List<Int32>> {
new List<Int32> { 2, 3 },
new List<Int32> { 3, 4 }
};
无需围绕List<List<T>>
编写包装器!
集合初始值设定项只是调用由 object 声明的Add
方法的语法糖,而List<T>
没有声明采用 2 个参数(或 1 个以上的任意数量的参数)的Add
方法。
但是,集合初始值设定项也会调用名为Add
的扩展方法。 这意味着我们可以这样写:
public static class ListExtensions
{
public static void Add<T>(this List<List<T>> list, params T[] items)
{
list.Add(new List<T>(items));
}
}
这让我们可以写:
IEnumerable<IEnumerable<int>> collection = new List<List<int>>()
{
{ 1, 2 },
{ 3, 4 },
};
值得注意的是,这种Add
方法只能作为扩展方法添加—— List<T>
不可能自己声明它。 这样做的原因是只有当列表包含其他列表时才有意义,并且无法定义仅适用于某些类型列表的实例方法。 但是,您可以在扩展方法上添加各种类似的限制。 您可以在List<T>
上编写扩展方法,该方法仅适用于T
是 class,或者实际上仅适用于T
是另一个列表时!
来自C# Programming Guide 中的 Object 和 Collection Initializers 文章:
集合初始值设定项允许您在初始化实现
IEnumerable
并具有Add
的集合类型时指定一个或多个元素初始值设定项作为实例方法或扩展方法。
因此,这里的问题是List<T>.Add()
没有适当的重载采用可变数量的 arguments。
如果你定义了一个自定义集合类型,你可以添加一个带有params
参数的Add()
方法:
class NestedList<T> : IEnumerable<IEnumerable<T>>
{
List<List<T>> _list;
public NestedList()
{
_list = new List<List<T>>();
}
public void Add(params T[] innerItems)
{
_list.Add(new List<T>(innerItems));
}
public IEnumerator<IEnumerable<TI>> GetEnumerator()
{
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
现在我们有一个Add()
方法,它接受可变数量的 arguments,您可以使用嵌套初始化程序:
IEnumerable<IEnumerable<int>> v2 = new NestedList<int> { { 1, 2 }, { 3, 4 } };
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.