2016-11-20 24 views
2

在C#中,我有一个类MyObj,它实现了一个接口IMyInterface在C#中,为什么从对象列表到接口列表的转换抛出异常?

我现在有MyObj中类的列表的集合:

IEnumerable<List<MyObj>> myObjGroups 

,我希望把它转换/转换为

IEnumerable<List<IMyInterface>> myInterfaceGroups 

,一切我都试过已抛出异常。

“”类型的异常出现在System.Core.dll但在用户代码中没有处理 其他信息:无法转换类型的对象“System.Collections.Generic.List ` 1 [MyObj中]'键入'System.Collections.Generic.List ` 1 [IMyInterface]'。

我曾尝试:

IEnumerable<List<IMyInterface>> myInterfaceGroups= new List<List<IMyInterface>>(myObjGroups.Cast<List<IMyInterface>>()); 

和:

IEnumerable<List<IMyInterface>> myList = myObjGroups.Cast<List<IMyInterface>>(); 

两者似乎在运行时抛出异常。

关于我在做什么错的任何建议?

+2

'名单'不是'名单'所以演员表无效。你可以使用IEnumerable >'。如果你需要内部列表然后'myObjGroups.Select(l => l.Cast ()。ToList())'。 – Lee

+1

就像@李说的那样,一个'List '不是'List '。这是因为'List '在'T'中不是协变的(它不是'List ')。那是因为这个类有成员,比如'Add'方法,使得协变不可能。一个接口,例如'IReadOnlyList '可以工作。如果只是'MyObj'是一个实现'IMyInterface'的引用类型,'IReadOnlyList '是一个'IReadOnlyList '。 'IEnumerable '是协变的。 –

回答

2

试试以下的方法:

IEnumerable<List<IMyInterface>> myInterfaceGroups = myObjGroups 
    .Select(l => l.Select(o => (IMyInterface)o).ToList()); 

或者如果你喜欢使用Cast<T>()扩展方法:

IEnumerable<List<IMyInterface>> myInterfaceGroups = myObjGroups 
    .Select(l => l.Cast<IMyInterface>().ToList()); 

编辑:解释有点

为了更好地理解为什么你有没有得到InvalidCastException异常,让我们尝试分解你的原始表达式:

IEnumerable<List<IMyInterface>> myInterfaceGroups = 
    new List<List<IMyInterface>>(myObjGroups.Cast<List<IMyInterface>>()); 

这相当于:

IEnumerable<List<IMyInterface>> myObjGroupsAsInterfaceList = myObjGroups 
    .Cast<List<IMyInterface>>() 
    .ToList(); 

IEnumerable<List<IMyInterface>> myInterfaceGroups = new List<List<IMyInterface>>(myObjGroupsAsInterfaceList); 

Cast<T>()扩展方法通过项目只是迭代并试图投每个项目键入T。我们可以更换Cast<T>()扩展方法的功能结合ToList<T>()与下面的代码片段:

List<List<IMyInterface>> myObjGroupsAsInterfaceList = new List<List<IMyInterface>>(); 
foreach (List<MyObj> myObjGroup in myObjGroups) 
{ 
    List<IMyInterface> myObjGroupAsInterface = myObjGroup; // Compile error! 
    myObjGroupsAsInterfaceList.Add(myObjGroupAsInterface); 
} 

所以根本的问题是,你不能一个List<MyObj>对象分配给List<IMyInterface>类型的变量。

要找到为什么上面是不可能的更多的解释,采取以下问题一看:C# variance problem: Assigning List<Derived> as List<Base>

0

你做错了什么。您不能将IEnumerable转换为List。列表是一个实际的数据化数据集合,而运行时需要重复执行IEnumerable以检索数据。

解决你的问题,你需要转换到IEnumerable<IMyInterface>

检查工作小提琴:Here(下同)

public class Program 
{ 
    static IEnumerable<List<MyObj>> Get() 
    { 
     yield return new List<MyObj>(); 
     yield return new List<MyObj>(); 
    } 

    static void Main() 
    { 
     IEnumerable<List<MyObj>> myObjGroups = Get(); 

     var result = myObjGroups.Cast<IEnumerable<IMyInterface>>(); 

     foreach(var val in result) 
      Console.WriteLine(val.Count()); 
    } 
} 
相关问题