好吧,想象一下看起来像这样的代码:
private List<ClientItem> ConvertToClientItems(BaseCollection<object> serverItems) {
serverItems.Add(new Buyer());
}
这应该编译,因为 aBuyer
是一个object
.
但是,如果您通过 a BaseCollection<Seller>
,您只是尝试将买家添加到卖家列表中。
因此,声明
BaseCollection<Seller>
是一个子类型BaseCollection<object>
仅当BaseCollection
确保泛型类型T
仅用于输出位置时才成立。上面的Add示例将用于T
输入位置。
要解决此问题,您有以下选择:
- 通过添加out关键字使 BaseCollection “协变” ,这需要删除任何
Add
方法。但是,这可能会使您的收藏变得毫无用处。
将协变接口传递给方法。如果您只需要阅读 serverItems
,请传递一个IEnumerable
已经是协变的 (并且您在 BaseCollection 已经实现的评论中提到IEnumerable
):
private List<ClientItem> ConvertToClientItems(IEnumerable<object> serverItems) {
// You can only read serverItems here, so we are fine.
}
使方法本身通用
private List<ClientItem> ConvertToClientItems<T>(BaseCollection<T> serverItems) {
// This also prevents the evil `Add` call, since you'd need to create
// an object of the correct type T first.
}