首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >似乎无法使通用协方差/协方差工作

似乎无法使通用协方差/协方差工作
EN

Stack Overflow用户
提问于 2016-03-04 16:30:16
回答 1查看 101关注 0票数 4

假设我有以下代码:

代码语言:javascript
复制
public interface IBaseMessage { }

public interface IMessageProcessor<in T> where T : IBaseMessage {
            void Process(T msg);
        }

public class RRMessage : IBaseMessage {
          //something here
        }

public class BaseMessageProcessor {
         //something here
        }

public class RRMessageProcessor : BaseMessageProcessor, IMessageProcessor<RRMessage> {
            public void Process(RRMessage msg) {
                Console.WriteLine("Processed RRMessage");
            }
        }

public Dictionary<Type, IMessageProcessor<IBaseMessage>> MessageProcessors = new Dictionary<Type, IMessageProcessor<IBaseMessage>>();

[Test]
public void Test1() {
     var msgProcessor = new RRMessageProcessor();
     MessageProcessors.Add(typeof(RRMessage), msgProcessor);
     }

我为接口IMessageProcessor启用了反向方差。为什么MessageProcessors.Add(typeof(RRMessage), msgProcessor);会导致编译时错误:

论点2:不能从“RRMessageProcessor”转换为“IMessageProcessor”

似乎它应该能够转换,因为RRMessageProcessor:IMessageProcessor<RRMessage:IBaseMessage>>如何才能让它工作呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-04 16:44:37

IMessageProcessor<in T>T中是逆变的,而不是协变的。这意味着允许采取以下措施:

代码语言:javascript
复制
class RRSubtype : RRMessage {}
IMessageProcessor<RRSubtype> p = new RRMessageProcessor();

您试图做的是静态不安全的,因为它允许您执行以下操作:

代码语言:javascript
复制
class NotRRMessage : IBaseMessage { }
IMessageProcessor<IBaseMessage> p = new RRMessageProcessor();
p.Process(new NotRRMessage());

因此,您需要动态地维护安全性,这似乎是在尝试使用字典Type -> Processor。因此,您可以创建不安全的包装器类型:

代码语言:javascript
复制
public class ProcessorWrapper<T> : IMessageProcessor<IBaseMessage> {
    private readonly IMessageProcessor<T> inner;
    public ProcessorWrapper(IMessageProcessor<T> inner) { this.inner = inner; }

    public void Process(IBaseMessage msg)
    {
        if(msg is T) { inner.Process((T)msg); }
        else throw new ArgumentException("Invalid message type");
    }
}

然后,您可以使用这些包装器构造您的列表,同时维护您想要的内部处理器。

代码语言:javascript
复制
public Dictionary<Type, IMessageProcessor<IBaseMessage>> MessageProcessors = new Dictionary<Type, IMessageProcessor<IBaseMessage>>();
MessageProcessors.Add(new ProcessorWrapper<RRMessage>(new RRMessageProcessor());
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35801156

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档