Covariant Generic List

The other day I was working with some generic lists of some custom classes.

All of these classes inherited from a common base class.

I wanted to write a method where I could pass any of my generic lists to this method and iterate over the list and execute some other code.

I thought this was a perfect example for passing a generic type into my method. I tried everything I know and could not get this to work.

I posted a question on the MSDN forums about my problem and John Grove pointed me at this article.

So it turns out what I was wanting was a Covariant Generic List.

I pretty much followed what was outlined in the article, but I will document here what I exactly did, namely because I had a hard time finding the solution to this problem.

This starts off by defining a interface for our base class.

public interface IClassInterface
{
   string Property1 { get; set; }
   string Property2 { get; set; }
}
Then we have to define our base class, plus any class that
inherits from it.
public class ClassA : IClassInterface
{
   public ClassA() {}
   
   public ClassA(ClassA objectA)
   {
      this.Property1 = objectA.Property1;
      this.Property2 = objectA.Property2;
   }

   public ClassA(string property1, string property2)
   {
      this.Property1 = property1;
      this.Property2 = property2;
   }

   public string Property1
   {
       get; set;
   }

   public string Property2
   {
       get; set;
   }
}

public class ClassB : ClassA
{
    public ClassB() {}

    public ClassB(ClassA objectA, string property3, string property4)
                             : base(objectA)
    {
       this.Property3 = property3;
       this.Property4 = property4;           
    }

    public string Property3
    {
       get; set;
    }

    public string Property4
    {
       get; set;
    }
}
Next we define a class that a returns enumerable generic list.
public class EnumerableGeneric<TClass, TInterface> 
              : IEnumerable<TInterface> where TClass : TInterface
{
   private IList<TClass> list;

   public EnumerableGeneric(IList<TClass> list)
   {
      this.list = list;
   }

   public IEnumerator<TInterface> GetEnumerator()
   {
      foreach (TClass item in list)
      {
         yield return item;
      }
   }

   IEnumerator IEnumerable.GetEnumerator()
   {
      return this.GetEnumerator();
   }
}
Next we define our method that we are going to use to perform
 some operation on each of the lists.
private void MyMethod(IEnumerable<IClassInterface> genericList)
{
   foreach (IClassInterface classVariable in genericList)
   {
      // Other code goes here.
   }
}
And finally we create our lists, populate some data and call our method.
List<ClassA> caInstance = new List<ClassA>();

caInstance.Add(new ClassA("A", "B"));
caInstance.Add(new ClassA("C", "D"));

List<ClassB> cbInstance = new List<ClassB>();
cbInstance.Add(new ClassB(new ClassA("E", "F"), "G", "H"));
cbInstance.Add(new ClassB(new ClassA("I", "J"), "K", "L"));

MyMethod(new EnumerableGeneric<ClassA, IClassInterface>(caInstance));

MyMethod(new EnumerableGeneric<ClassB, IClassInterface>(cbInstance));


I appreciate John Grove for taking the time on the MSDN forums to answer my question and also to Stefan Delmarco for posting the original article.

Hope this helps somebody else, I know it helped me.

 

Published Sunday, April 19, 2009 8:47 PM by dmccollough

Comments

# re: Covariant Generic List

Monday, April 20, 2009 12:10 AM by Bill McCarthy

wouldn't it be simpler to use LINQ, eg:

MyMethod(caInstance.Select(x => (IClassInterface)x));

or:

MyMethod(caInstance.Cast<IClassInterface>());

etc.

# re: Covariant Generic List

Monday, April 20, 2009 7:56 AM by dmccollough

Yes, it looks like it would be easier to user LINQ. Thanks for the tip.

# re: Covariant Generic List

Monday, April 20, 2009 3:32 PM by JD

Why couldn't you just write your method as a generic method? Something like this:

private void MyMethod<T>(IList<T> genericList) where T : MyBaseClass {...}

You'd still get access to all the methods of your base class and avoid a lot of gyrations.

# re: Covariant Generic List

Monday, April 20, 2009 7:11 PM by dmccollough

I will certainly give this a try. I'm always looking for a simpler method.