简体   繁体   中英

How do I convert a List<interface> to List<concrete>?

I have an interface defined as:

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

and a class that implements that interface:

public class MyClass : MyInterface {
     object foo { get; set; }
}

I then create a function that returns a ICollection like so:

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

It would compile but would throw a

Unable to cast object of type 'System.Collections.Generic.List 1[MyInterface]' to type 'System.Collections.Generic.IEnumerable 1[MyClass]'.

exception. What am I doing wrong?

A List<MyInterface> cannot be converted to a List<MyClass> in general, because the first list might contain objects that implement MyInterface but which aren't actually objects of type MyClass .

However, since in your case you know how you constructed the list and can be sure that it contains only MyClass objects, you can do this using Linq:

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

But a List<MyInterface> is emphatically not a List<MyClass> .

Think:

interface IAnimal { }

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

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

Then

var cats = (List<Cat>)list;

Absurd!

Also,

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

Absurd!

Further

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

Absurd!

Instead, you could say

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

您可以使用Cast<>扩展方法:

return list.Cast<MyClass>();

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

It is possible and that's where the generics shine! Here is a simple example:

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

And now you need to declare your method (or your class) generic like this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM