我需要调用一个接受接口作为参数的方法。我用作参数的对象实现了接口但是我仍然遇到编译错误。我做错了什么?
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
{
}
答案 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
{
//...
}