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