[英]Interface inheritance with generic lists
我想為一個簡單的項目構建一個生產者和消費者的通用系統。
我現在擁有的是什么
public interface IMessage { }
public interface Message1 : IMessage { }
public interface Message2 : IMessage { }
public interface IConsumer<T> { }
public interface IProducer<T> { }
public class Mop1 : IConsumer<Message1>, IProducer<Message2>
{
}
class Program
{
static void Main(string[] args)
{
var list = new List<IConsumer<IMessage>>();
var mop = new Mop1();
list.Add(mop); // Error occurs here
}
}
最后一行給出了一個錯誤,例如cannot convert from 'Mop1' to 'IConsumer<GenericPubSub.IMessage>'
但是Mop1實現了IMessage派生類型的IConsumer。 這是一些差異問題嗎? 這有什么問題?
這很棘手。 你可以使用co / contravariance,但......
我會稍微簡化代碼。 只是為了關閉編譯器,你可以這樣做:
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
會像另一個答案所建議的那樣做,但它從根本上解決了什么問題。 讓我說,現在你想要建立你的界面:
public interface IConsumer<out IMessage>
{
object Process (IMessage m);
}
aaaand它不會編譯。 因為簡單地說如果你說出out IMessage
就意味着返回類型應該來自IMessage
,而不是參數類型。
所以你會這樣:
public interface IConsumer<in IMessage>
{
object Process (IMessage m);
}
public class Mop1 : IConsumer<Message1>
{
public object Process (Message1 msg)
{
return null;
}
}
使其編譯並有效。 但現在你的list.Add(mop);
不管用。 這是理所當然的,因為你的Mop1
確實不能轉換為IConsumer<IMessage>
因為如果它是以下代碼將是可能的:
list[0].Process (new Message2 ());
並且它是不可能的,因為Mop1只接受Message1
。
所以回答這個問題。 使用消息調度和純C#編譯器功能,您無法真正做任何有意義的事情。 我知道它要去哪里,你想要用消息和東西進行靜態輸入。 遺憾的是,您不能擁有使用通用列表中特定消息的消費者列表,您必須擁有像bool CanProcess(IMessage); IMessage Process(IMessage);
這樣的抽象簽名bool CanProcess(IMessage); IMessage Process(IMessage);
bool CanProcess(IMessage); IMessage Process(IMessage);
並投入內部。 您也可以使用自定義屬性和反射稍微好一些,但同樣,不僅僅是使用C#編譯器。
如果您計划使用這些接口實現典型的生產者,消費者模式,請首先查看此答案 。
如果您希望IConsumer<TMessage>
也是 IConsumer<TMessageBase>
,其中TMessageBase
是TMessage
繼承或實現的任何類型,那么您需要使您的泛型參數協變。 使用out
修飾符。
public interface IConsumer<out T> { }
現在IConsumer<Message1>
可以分配給IConsumer<IMessage>
,因為Message1
實現了IMessage
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.