Have you noticed that if you fill a generic List with a concrete class that implements an interface, the generic List does not think it is filled with objects of that interface? And you can't cast the list to a List of the interface.
Let's look at a simple example where we have an IPerson interface and a concrete class, Person, implementing IPerson:
namespace ConvertingGenericLists
{
public interface IPerson
{
string Name { get; set; }
}
public class Person : IPerson
{
public string Name { get; set; }
}
}
Nothing strange. However, if we create a List<Person> it is not a List<IPerson> and the compiler will not tolerate a cast like (List<IPerson>).
However, every element in the list is both of type Person and IPerson, but the list itself is of Person.
The neat trick is to use the ConvertAll()-method in List and with a simple lambda-method convert it.
Like this (PersonList is a List<Person>):
IPersonList = PersonList.ConvertAll(c => (IPerson) c);
Now the lists contents is that of the interface, but as you will see in the code below, every element is still of IPerson and Person.
And here is a complete example using NUnit tests:
using System.Collections.Generic;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
namespace ConvertingGenericLists
{
[TestFixture]
public class Tests
{
private List<Person> PersonList;
private List<IPerson> IPersonList;
[TestFixtureSetUp]
public void Setup()
{
PersonList = new List<Person>
{
new Person {Name = "Aurel"},
new Person {Name = "Thomas"},
new Person {Name = "Lasse"}
};
//And the magic of ConvertAll() and lamdba:
IPersonList = PersonList.ConvertAll(c => (IPerson) c);
}
[Test]
public void PersonList_Is_Of_Base_Type_Only()
{
Assert.That(PersonList, Is.InstanceOfType(typeof(List<Person>)));
Assert.That(PersonList, Is.InstanceOfType(typeof(IList<Person>)));
Assert.That(PersonList, Is.InstanceOfType(typeof(IEnumerable<Person>)));
//An element in PersonList is indeed of type IPerson:
Assert.That(PersonList[0], Is.InstanceOfType(typeof(IPerson)));
//But PersonList is not a list of IPersons!
Assert.That(PersonList, Is.Not.InstanceOfType(typeof(List<IPerson>)));
}
[Test]
public void IPersonList_Is_A_List_Of_IPerson()
{
Assert.That(IPersonList, Is.InstanceOfType(typeof(IList<IPerson>)));
Assert.That(IPersonList, Is.InstanceOfType(typeof(List<IPerson>)));
Assert.That(IPersonList, Is.InstanceOfType(typeof(IEnumerable<IPerson>)));
//IPersonlist is not of the implementing type anymore:
Assert.That(IPersonList, Is.Not.InstanceOfType(typeof(List<Person>)));
Assert.That(IPersonList, Is.Not.InstanceOfType(typeof(IList<Person>)));
Assert.That(IPersonList, Is.Not.InstanceOfType(typeof(IEnumerable<Person>)));
//But an element in IPersonList is STILL a Person and a IPerson!
Assert.That(IPersonList[0], Is.InstanceOfType(typeof(Person)));
Assert.That(IPersonList[0], Is.InstanceOfType(typeof(IPerson)));
}
}
}