I have following contravariant interface and its implementation
public interface IMessageSender<in TMessage>
{
Task SendAsync(TMessage @object);
}
public class MessageSender<TMessage> : IMessageSender<TMessage>
{
public Task SendAsync(TMessage @object)
{
throw new NotImplementedException();
}
}
I have hierarchy of classes that should represent TMessage .
public class Base { }
public class Descendant1 : Base { }
public class Descendant2 : Base { }
So I have two senders for simplicity
var descendant1Sender = new MessageSender<Descendant1>();
var descendant2Sender = new MessageSender<Descendant2>();
How can I cast these two senders to common interface to pass for example to the method. For example.
static void SomeMethod( IServiceBusMessageSender<Base> baseSender)
{
baseSender.SendAsync(new Descendant1());
}
SomeMethod(descendant1Sender); //This won't compile because of contravariance
You can't treat
IMessageSender<Descendant1>asIMessageSender<Base>because it is not one, contravariance or not, it requires parameter to beDescendant1orDescendant1's descendant.Contravariance allows to use
IMessageSender<Base>asIMessageSender<Descendant1>, not vice versa. I.e. the following will work (and will result in compilation error if you make the interface invariant):Demo
UPD
As workaround you can look into introducing non-generic version of interface and/or some typechecking:
The idea being that
SomeMethodwill check if handler can send the message.