3

我需要调用一个接受接口作为参数的方法。我用作参数的对象实现了接口,但是我仍然遇到编译错误。我究竟做错了什么?

public class ViewModel 
{
    public ViewModel()
    {
        QueueManager<CFMessage<CFQueueItem>, CFQueueItem> q = new QueueManager<CFMessage<CFQueueItem>, CFQueueItem>();
        DoSomething(q);     // This line does not compile:  Cannot convert from QueueManager<CFQueueItem> to QueueManager<IQueueItem>
    }

    public void DoSomething(QueueManager<IQueueMessage<IQueueItem>, IQueueItem> queueManager)
    {

    }
}

public interface IQueueMessage<T> where T : IQueueItem
{
    int ID { get; set; }
}

public interface IQueueItem
{
    int ID { get; set; }
}

public class CFMessage<CFQueueItem> : IQueueMessage<CFQueueItem> where CFQueueItem : IQueueItem
{
    public int ID { get; set; }
}

public class CFQueueItem : IQueueItem
{
    public int ID { get; set; }
}

public class QueueManager<T, Q>
    where T : IQueueMessage<Q>
    where Q : IQueueItem
{

}
4

2 回答 2

4

您可以通过使用概念covariance来解决,将 interface 定义IQueueMessagecovariant,使用关键字out

public interface IQueueMessage<out T> where T : IQueueItem
{
}

IQueueManager然后为:创建新的协变接口QueueManager

public interface IQueueManager<out T, out Q> where T : IQueueMessage<Q>
                                             where Q : IQueueItem
{
}

public class QueueManager<T, Q> : IQueueManager<T, Q>
    where T : IQueueMessage<Q>
    where Q : IQueueItem
{

}

然后您可以将此接口用于方法DoSomething

public void DoSomething(IQueueManager<IQueueMessage<IQueueItem>, IQueueItem> queueManager)
{
}

您的代码将成功编译:

public ViewModel()
{
    var q = new QueueManager<CFMessage<CFQueueItem>, CFQueueItem>();
    DoSomething(q);
}
于 2012-10-13T18:21:35.463 回答
3

尝试使方法通用;即使不能使接口成为协变的,这也将起作用:

public void DoSomething<TMessage, TItem>(QueueManager<TMessage, TItem> queueManager) 
    where TMessage : IQueueMessage<TItem>
    where TItem : IQueueItem
{ 
     //...
} 
于 2012-10-13T18:33:01.773 回答