可以投射C#泛型参数吗?

时间:2013-10-10 21:59:24

标签: c# casting

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

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

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

ConvertToClientItems(approvedSellers);

其中approvedSellers的类型为BaseCollection<Seller> - Seller是我无法控制的类。

这应该不可能吗? Visual Studio向我提出错误,指出它无法将BaseCollection<seller>强制转换为BaseCollection<object>

2 个答案:

答案 0 :(得分:2)

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

private List<ClientItem> ConvertToClientItems(BaseCollection<object> serverItems) {
    serverItems.Add(new Buyer());
}

这应该编译,因为Buyerobject

但是,如果您传递BaseCollection<Seller>,则只是尝试将买家添加到卖家列表中。

因此,声明

BaseCollection<Seller>BaseCollection<object>

的子类型

仅在BaseCollection确保通用类型T仅用于输出位置时才有效。上面的添加示例会在输入位置使用T


要解决此问题,您有以下选择:

  • 通过添加out keyword使BaseCollection“协变”,这将需要删除任何Add方法。但是,这可能会使您的收藏无用。
  • 将协变接口传递给方法。如果您只需要读取 serverItems,请传递一个已经协变的IEnumerable(并且您在评论中提到BaseCollection已经实现了IEnumerable):< / p>

    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.
    }
    

答案 1 :(得分:1)

在BaseCollection中,你必须使用&#34; out&#34;来进行T协变。关键字。

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

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

public interface BaseCollection<out T>