C#类型转换,如何避免错误?

3

一位同事有一个对象,其中包含许多通用列表集合。列表中的每个类型都实现了给定的接口。他希望能够创建一个包含所有其他列表的列表,以便可以循环遍历并调用对象实现的方法。下面是一个简单的示例。

 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。

3
你正在使用哪个版本的.NET? - Oded
通过运行上述代码,您已经可以回答“是否可能”的问题了。 - RQDQ
@RQDQ - 上述代码出现错误,OP正在寻求解决方案。 - Oded
4个回答

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();
}

4
您不能使用ListIList进行此操作,因为这些类型不是协变的。换句话说,如果您有一个List<IClean>,您应该能够向其中添加一个Dx,但如果您有一个List<Proc>,则不应该。因此,List<Proc>不是List<IClean>
从.NET 4开始,您可以使用IEnumerable<>实现此目的:
 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();
     }
 }

3
如何考虑:
using System.Linq;

...

foreach( var clean in procs.Cast<IClean>().Concat(dxs.Cast<IClean>()) )
{
    clean.Clean();
} 

0
这是一个 LinqPad 代码片段,将输出以下内容:

Proc cleaned Dx cleaned Dx cleaned

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();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接