To podchwytliwy przypadek. Możesz użyć ko/contravariance, ale ...
Uproszczę trochę kod. Wystarczy zamknąć kompilator można to zrobić:
public interface IMessage { }
public interface Message1 : IMessage { }
public class Mop1 : IConsumer<Message1>
{
}
public interface IConsumer<out IMessage>
{
}
class Program
{
static void Main(string[] args)
{
var list = new List<IConsumer<IMessage>>();
var mop = new Mop1();
list.Add(mop); // Error occurs here
}
}
out IMessage
rade jak sugeruje inną odpowiedź, ale zasadniczo nie ma niczego naprawić. Pozwól mi pokazać, teraz chcesz, aby twój interfejs:
public interface IConsumer<out IMessage>
{
object Process (IMessage m);
}
aaa i nie będzie się kompilować. Ponieważ po prostu umieścić, jeśli mówisz out IMessage
oznacza to, że typy zwracane powinny pochodzić z IMessage
, a nie typów parametrów.
Więc trzeba będzie to w ten sposób:
public interface IConsumer<in IMessage>
{
object Process (IMessage m);
}
public class Mop1 : IConsumer<Message1>
{
public object Process (Message1 msg)
{
return null;
}
}
Aby uczynić go skompilować i ważność. Ale teraz twoje list.Add(mop);
nie będzie działać. I słusznie, ponieważ Mop1
nie jest istotnie rzutować na IConsumer<IMessage>
bo gdyby był następujący kod byłoby możliwe:
list[0].Process (new Message2());
i nie jest możliwe, ponieważ MOP1 akceptuje tylko Message1
.
Aby odpowiedzieć na pytanie. Naprawdę nie można zrobić nic sensownego z wysyłaniem wiadomości i czystymi kompilatorami C#. Widzę, dokąd zmierza, chciałeś statycznego pisania z wiadomościami i podobnymi rzeczami. Niestety, nie możesz mieć listy konsumentów, którzy zużywają określone wiadomości na liście ogólnej, musisz mieć abstrakcyjne podpisy, takie jak bool CanProcess(IMessage); IMessage Process(IMessage);
i wrzucać je do środka. Możesz także zrobić to nieco lepiej dzięki niestandardowym atrybutom i refleksji, ale znowu nie tylko z kompilatorem C#.
To całkiem fajne. –
Poza tym, że nie jest to dokładnie to, chociaż kompiluje.Konsument pobiera wiadomości, więc powinno to być "w", ale wtedy nie będzie się kompilować. Oryginalna logika jest zepsuta. – Andrey
@Andrey Musimy przyjrzeć się sygnaturom metod, aby dowiedzieć się, co powinno być i gdzie się znajduje. W tej chwili interfejsy są całkowicie puste. –