The crux of your issue is that you are trying to create a container that is covariant, or where you are assigning a more derived type to a more generic type (CheeseCake
to
ISnack
) while simultaneously attempting to call an interface method that should be contravariant, or implementing a more derived type (CheeseCake
). This type of bi-directional variance is illegal in C#.
As a result, you have essentially two options. You can abandon the covariance during your container creation which allows you to maintain contravariance in your implementation, or you can use covariance during your container creation, but you will be forced to cast to your target type in your implementation in order to satisfy the interface.
The former with a contravariant IWrapper<in TSnack>
definition:
CheeseCakeContainer wrappedSnack = new CheeseCakeContainer();
var c1 = new CheeseCake();
wrappedSnack.Wrap(c1);
public interface ISnack { }
public interface IWrapper<in TSnack> where TSnack : ISnack
{
void Wrap(TSnack snack);
}
public class CheeseCakeContainer : IWrapper<CheeseCake>
{
public void Wrap(CheeseCake snack)
{
snack.Type = "Strawberry";
}
}
public class CheeseCake : ISnack
{
public string Type { get; set; }
}
The latter:
IWrapper<ISnack> wrappedSnack = new CheeseCakeContainer();
var c1 = new CheeseCake();
wrappedSnack.Wrap(c1);
public interface ISnack { }
public interface IWrapper<out TSnack> where TSnack : ISnack
{
void Wrap(ISnack snack);
}
public class CheeseCakeContainer : IWrapper<CheeseCake>
{
public void Wrap(ISnack snack)
{
((CheeseCake)snack).Type = "Strawberry";
}
}
public class CheeseCake : ISnack
{
public string Type { get; set; }
}