一个同事有一个对象,上面有一堆通用列表集合。列表中的每种类型都实现给定的接口。他希望能够创建一个包含所有其他列表的列表,以便他可以遍历并调用对象实现的方法。下面是一个简单的例子。
List<Dx> dxs = new List<Dx>();
dxs.Add(new Dx());
dxs.Add(new Dx());
List<Proc> procs = new List<Proc>();
procs.Add(new Proc());
List<List<IClean>> lists = new List<List<IClean>>();
lists.Add(procs); // Error here
lists.Add(dxs); // Error here
foreach (List<IClean> list in lists)
{
foreach (IClean i in list)
{
i.Clean();
}
}
Dx和Proc都实现了IClean。这是目标。这样的事情可能吗?或者,这是不好的编程吗?
.NET 4.0版
答案 0 :(得分:9)
您可以只拥有一个List<IClean>
来保存IClean
的两种实现。
var list = new List<IClean>();
list.Add(new Dx());
list.Add(new Proc());
foreach(var clean in list)
{
clean.Clean();
}
此外,如果您确实需要维护两个单独的实现列表然后一起处理它们,您可以执行以下操作:
var dx = new List<Dx>();
var proc = new List<Proc>();
List<IClean> list = new List<IClean>();
list.AddRange(dx);
list.AddRange(proc);
foreach(var clean in list)
{
clean.Clean();
}
答案 1 :(得分:4)
您无法使用List
或IList
执行此操作,因为这些类型不是协变的。换句话说,如果您有List<IClean>
,则应该可以向其添加Dx
,但如果您有List<Proc>
,则不应该。List<Proc>
。因此,List<IClean>
不是IEnumerable<>
。
从.NET 4开始,您可以使用 List<Dx> dxs = new List<Dx>();
dxs.Add(new Dx());
dxs.Add(new Dx());
List<Proc> procs = new List<Proc>();
procs.Add(new Proc());
List<IEnumerable<IClean>> lists = new List<IEnumerable<IClean>>();
lists.Add(procs);
lists.Add(dxs);
foreach (List<IClean> list in lists)
{
foreach (IClean i in list)
{
i.Clean();
}
}
执行此操作:
{{1}}
答案 2 :(得分:3)
怎么样:
using System.Linq;
...
foreach( var clean in procs.Cast<IClean>().Concat(dxs.Cast<IClean>()) )
{
clean.Clean();
}
答案 3 :(得分:0)
以下是LinqPad代码段,它将输出以下内容:
Proc清理 Dx清理干净 Dx清理
void Main()
{
List<IClean> dxs = new List<IClean>();
dxs.Add(new Dx());
dxs.Add(new Dx());
List<IClean> procs = new List<IClean>();
procs.Add(new Proc());
List< List<IClean> > lists = new List< List<IClean> >();
lists.Add(procs);
lists.Add(dxs);
foreach (List<IClean> list in lists)
{
foreach (IClean i in list)
{
i.Clean();
}
}
}
// Define other methods and classes here
public interface IClean
{
void Clean();
}
public class Dx : IClean
{
public void Clean()
{
"Dx cleaned".Dump();
}
}
public class Proc : IClean
{
public void Clean()
{
"Proc cleaned".Dump();
}
}