5

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.

2 Answers 2

6

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);
Sign up to request clarification or add additional context in comments.

3 Comments

Yes, I did try that. It still complained when passing the Distro object. UpdateDistro<DistroItem>(myDistro) threw the same error.
I see this is getting upvotes. I'll mark it as the answer if you can show me the proper way to call the method.
Thank you. Sorry to be a pain. I had remnants from other testing where I was casting to the interface types, etc. This works as desired. Much appreciated!
0

You can define a covariant generic parameter in your interface, you need to change the interface a little bit though to ensure that T is not uses contravariantly:

public interface IOrder<out T> where T : IOrderItem
{
    IEnumerator<T> Items { get; }
}

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

}

To define T as coverient parameter (out), allows for implicit conversion of classes that implement your variant interfaces.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.