如何将List<List<Int32>>的初始化简化为IEnumerable<IEnumerable<Int32>>?
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 }
};
来自Object and Collection Initializers article in the C# Programming Guide:
Collection initializers let you specify one or more element initializers when you initialize a collection type that implements IEnumerable
and has Add
with the appropriate signature as an instance method or an extension method.
所以,这里的问题是 List<T>.Add()
没有适当的重载需要可变数量的参数。
如果您定义自定义集合类型,您可以添加一个采用 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()
方法,您可以使用嵌套的初始值设定项:
IEnumerable<IEnumerable<int>> v2 = new NestedList<int> { { 1, 2 }, { 3, 4 } };
无需围绕 List<List<T>>
编写包装器!
集合初始值设定项只是调用对象声明的名为 Add
的方法的语法糖,而 List<T>
不声明采用 2 个参数(或任何参数)的 Add
方法以上参数个数 1).
但是,一个集合初始化器也会调用一个名为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
是另一个列表时才适用!
我正在进行以下集合初始化:
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 }
};
来自Object and Collection Initializers article in the C# Programming Guide:
Collection initializers let you specify one or more element initializers when you initialize a collection type that implements
IEnumerable
and hasAdd
with the appropriate signature as an instance method or an extension method.
所以,这里的问题是 List<T>.Add()
没有适当的重载需要可变数量的参数。
如果您定义自定义集合类型,您可以添加一个采用 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()
方法,您可以使用嵌套的初始值设定项:
IEnumerable<IEnumerable<int>> v2 = new NestedList<int> { { 1, 2 }, { 3, 4 } };
无需围绕 List<List<T>>
编写包装器!
集合初始值设定项只是调用对象声明的名为 Add
的方法的语法糖,而 List<T>
不声明采用 2 个参数(或任何参数)的 Add
方法以上参数个数 1).
但是,一个集合初始化器也会调用一个名为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
是另一个列表时才适用!