У меня есть классы Message1D и Message2D, наследуемые от Message:
public abstract class Message {}
public class Message1D : Message {}
public class Message2D : Message {}
Интерфейс IFoo и классы Bar и Baz, реализующие его:
public interface IFoo<out G, in T>
where G : Message
where T : Message
{
G PassMessage(T input);
}
public class Bar : IFoo<Message1D, Message1D>
{
public Message1D PassMessage(Message1D input)
{
throw new NotImplementedException();
}
}
public class Baz : IFoo<Message2D, Message2D>
{
public Message2D PassMessage(Message2D input)
{
throw new NotImplementedException();
}
}
И вот здесь моя проблема. Как добавить в список экземпляры Foo и Bar?
public class Network
{
private List<IFoo<Message, Message>> messages = new List<IFoo<Message, Message>>();
public void AddBar()
{
messages.Add(new Bar());
}
public void AddBaz()
{
messages.Add(new Baz());
}
}
У меня исключение:
Can not convert
BartoIFoo<Message,Message>
и
Can not convert
BaztoIFoo<Message,Message>
Как я могу добавить экземпляры Bar и Baz в список?





How can I add Bar and Baz instances to the List?
Вы не можете, потому что вы пытаетесь рассматривать входящее сообщение как ковариантное, но контравариантное. Вы можете рассматривать IFoo<Message1D, Message> как IFoo<Message, Message>, но вы не можете рассматривать IFoo<Message, Message1D> как IFoo<Message, Message>. Если бы это было правильно, то кому-то было бы разрешено передавать 2D-сообщения в ваш объект, который может обрабатывать только 1D-сообщения.
Как упоминал @Servy, это невозможно в вашей текущей архитектуре, и вам, вероятно, следует переделать ее.
Но если каким-то образом вы можете гарантировать безопасность типов, вы можете попробовать явно реализовать IFoo<Message1D, Message> в дополнение к IFoo<Message1D, Message1D> следующим образом:
public class Bar : IFoo<Message1D, Message1D>, IFoo<Message1D, Message>
{
public Message1D PassMessage(Message1D input)
{
// ...
}
Message1D IFoo<Message1D, Message>.PassMessage(Message input)
{
try
{
return PassMessage((Message1D) input);
}
catch (InvalidCastException)
{
// Message2D passed, handling exception
// ...
}
}
Аналогично реализуем IFoo<Message2D, Message> для Baz.
Это заставит ваш код работать, но, скорее всего, это не лучшее решение для вас.
красивая! Спасибо, сэр!