如何将List <interface>转换为List <concrete>?</concrete> </interface>

时间:2011-05-16 15:37:54

标签: c# generics interface

我的界面定义为:

public interface MyInterface {
     object foo { get; set; };
}

以及实现该接口的类:

public class MyClass : MyInterface {
     object foo { get; set; }
}
然后我创建一个返回ICollection的函数,如下所示:

public ICollection<MyClass> Classes() {
    List<MyClass> value;

    List<MyInterface> list = new List<MyInterface>(
        new MyInterface[] {
            new MyClass {
                ID = 1
            },
            new MyClass {
                ID = 1
            },
            new MyClass {
                ID = 1
            }
        });

    value = new List<MyClass>((IEnumerable<MyClass>) list);

    return value;
}

它会编译,但会抛出

  

无法投射类型的对象   'System.Collections.Generic.List 1[MyInterface]' to type 'System.Collections.Generic.IEnumerable 1 [MyClass的]'。

异常。我做错了什么?

6 个答案:

答案 0 :(得分:50)

一般来说List<MyInterface>无法转换为List<MyClass>,因为第一个列表可能包含实现MyInterface但实际上不是MyClass类型对象的对象

但是,因为在您的情况下,您知道如何构建列表并确保它只包含MyClass个对象,您可以使用Linq执行此操作:

return list.ConvertAll(o => (MyClass)o);

答案 1 :(得分:32)

List<MyInterface>强调的不是List<MyClass>

想:

interface IAnimal { }

class Cat : IAnimal { }
class Dog : IAnimal { }

var list = new List<IAnimal> { new Cat(), new Dog() };

然后

var cats = (List<Cat>)list;

荒诞!

此外,

var cats = list.Cast<Cat>();

荒诞!

另外

var cats = list.ConvertAll(x => (Cat)x);

荒诞!

相反,你可以说

var cats = list.OfType<Cat>();

答案 2 :(得分:1)

您可以使用#!/usr/bin/env bash TARGET_DIR=~/logs/docker_logs mkdir -p "$TARGET_DIR" for name in `sudo docker ps --format '{{.Names}}'`; do path=$(sudo docker inspect --format='{{.LogPath}}' $name) sudo cp -rf "$path" "$TARGET_DIR"/$name.log done 扩展方法:

Cast<>

答案 3 :(得分:1)

使用Cast如下:

list.Cast<T>().ToList()

答案 4 :(得分:0)

我发现Automapper对于将接口转换为具体类非常有用。

答案 5 :(得分:0)

这是可能的,这就是泛型的亮点! 这是一个简单的示例:

public interface ICountable
{
     int Count { get; set; }
}

public class PopularName : ICountable
{
    public string Name { get; set; }
    public int Count { get; set; }
}

public class PopularSize : ICountable
{
     public int Size { get; set; }
     public int Count { get; set; }
}

现在您需要像这样声明您的方法(或您的类)通用:

public bool HasAnyValue<T>(List<T> countableModel) where T : ICountable
{
    return countableModel.Count > 0;
}