Reputation: 4125
I have classes Message1D
and Message2D
both inherit from Message
:
public abstract class Message {}
public class Message1D : Message {}
public class Message2D : Message {}
An interface IFoo
and classes Bar
and Baz
, which implement it:
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();
}
}
And my problem is here. How can I add Foo and Bar instances to the list ?
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());
}
}
I have an exception:
Can not convert
Bar
toIFoo<Message,Message>
and
Can not convert
Baz
toIFoo<Message,Message>
How can I add Bar
and Baz
instances to the List ?
Upvotes: 3
Views: 110
Reputation: 1286
As @Servy mentioned, it is not possible in your current architecture and you should probably remake it.
But if somehow you can guarantee type safety, then you can try to explicitly implement IFoo<Message1D, Message>
in addition to IFoo<Message1D, Message1D>
as follows:
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
// ...
}
}
Similarly implement IFoo<Message2D, Message>
for Baz
.
That will make your code work, but it is most likely not the best decision for you.
Upvotes: 0
Reputation: 203817
How can I add Bar and Baz instances to the List?
You can't, because you're trying to treat the input message as if it's covariant, but it's contravariant. You can treat an IFoo<Message1D, Message>
as an IFoo<Message, Message>
, but you can't treat an IFoo<Message, Message1D>
as an IFoo<Message, Message>
. If that were valid, then someone would be allowed to pass in 2D messages into your object that can only handle 1D messages.
Upvotes: 4