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

29,432

Solution 1

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

Solution 2

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

Solution 3

You could use Cast<> extension method:

return list.Cast<MyClass>();
Share:
29,432

Related videos on Youtube

acermate433s
Author by

acermate433s

Updated on October 01, 2020

Comments

  • acermate433s
    acermate433s over 3 years

    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.List1[MyInterface]' to type 'System.Collections.Generic.IEnumerable1[MyClass]'.

    exception. What am I doing wrong?

  • Ritch Melton
    Ritch Melton about 13 years
    This will work in .Net 2.0+ and not just LINQ as System.Collections.Generic.List<> supports ConvertAll<T>() directly.
  • JSBձոգչ
    JSBձոգչ about 13 years
    Thanks, @Ritch. I thought that ConvertAll was a Linq method, but I hadn't bothered to check.
  • Paolo Moretti
    Paolo Moretti about 13 years
    Actually, if you are sure that your list contains only MyClass objects, you should use Enumerable.Cast<TResult> Method, and you will get an InvalidCastException if an element in the sequence cannot be cast to MyClass.
  • acermate433s
    acermate433s about 13 years
    I see. I was confused because you can cast an interface to its concrete class. Thanks.
  • AkshayM
    AkshayM almost 11 years
    @PaoloMoretti: Thanks - your method saved a lot of effort. I am using telerik wpf components and in the RadDataFilter the return value is a list of interfaces and I have to do a long foreach with typecasting and string match switches and if else. Now I can use linq. :)
  • aloisdg
    aloisdg almost 6 years
    Can you add some details?