1

我写了一个带有签名的方法:

private List<ClientItem> ConvertToClientItems(BaseCollection<object> serverItems)

我试图以下列方式调用它:

ConvertToClientItems(approvedSellers);

whereapprovedSellers是类型BaseCollection<Seller>-Seller作为一个我无法控制的类。

这不应该是可能的吗?Visual Studio 向我抛出一个错误,说它不能BaseCollection<seller>转换为BaseCollection<object>.

4

2 回答 2

2

好吧,想象一下看起来像这样的代码:

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.
    }
    
于 2013-10-11T05:33:43.267 回答
1

在 BaseCollection 中,您必须使用“out”关键字使 T 协变。

更多信息http://msdn.microsoft.com/en-us/library/dd233059.aspx

(IEnumerable 有效,因为它是协变的。)

public interface BaseCollection<out T>
于 2013-10-11T01:05:18.340 回答