无法转换泛型类型参数

时间:2012-10-13 18:09:31

标签: c#

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

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
{

}

2 个答案:

答案 0 :(得分:4)

您可以使用概念covariance,使用关键字IQueueMessage将接口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);
}

答案 1 :(得分:3)

尝试使方法通用;即使界面不能协变,这也会起作用:

public void DoSomething<TMessage, TItem>(QueueManager<TMessage, TItem> queueManager) 
    where TMessage : IQueueMessage<TItem>
    where TItem : IQueueItem
{ 
     //...
}