Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I pass two similar concrete objects to a method with interface parameters that implement generics in C#?

I have the following interface declarations:

interface IOrder<T> where T: IOrderItem
{
     IList<T> Items { get; set; }
}

interface IDistro<T> : IOrder<T> where T: IOrderItem
{

}

I have two concrete classes, like so:

// DistroItem implements IOrderItem
public class Distro : IDistro<DistroItem>
{
    public IList<DistroItem> Items { get; set; }
}

// PerishableOrderItem implements IOrderItem
public class PerishableOrder : IDistro<PerishableOrderItem>
{       
    public IList<PerishableOrderItem> Items { get; set; }
}

Lastly, I have a static service method for saving to the database:

public static void UpdateDistro(IDistro<IOrderItem> distro)
{

}

My problem is, how do I pass a distro of either concrete type to my static method? The following doesn't compile:

Distro d = new Distro();
UpdateDistro(d);

The error is:

The best overloaded method match for UpdateDistro(IDistro<IOrderItem>)' has some invalid arguments

Is contravariance the answer? I tried adding <in T> to the original interface declaration, but that added more errors that I was unable to resolve. This is my first in depth foray into interfaces and I'm sure generics is adding complexity, so there might be a fundamental lack of understanding here.

like image 398
IronicMuffin Avatar asked Mar 19 '12 15:03

IronicMuffin


1 Answers

Have you tried this:

public static void UpdateDistro<T>(IDistro<T> distro) 
  where T : IOrderItem
{  
} 

EDIT:

With empty implementations for DistroItem and PerishableItem classes (both implementing IOrderItem), I've got the following compiling without an error:

Distro d = new Distro();
PerishableOrder p = new PerishableOrder();

UpdateDistro(d);
UpdateDistro(p);
like image 81
Mike Cowan Avatar answered Oct 17 '22 16:10

Mike Cowan