是否可以强制转换 C# 泛型参数
本文关键字:泛型 参数 转换 是否 | 更新日期: 2023-09-27 18:34:54
我用签名编写了一个方法:
private List<ClientItem> ConvertToClientItems(BaseCollection<object> serverItems)
我尝试以以下方式调用它:
ConvertToClientItems(approvedSellers);
其中approvedSellers
属于 BaseCollection<Seller>
型 - Seller
是我无法控制的类。
这不应该吗?Visual Studio向我抛出了一个错误,说它无法将BaseCollection<seller>
转换为BaseCollection<object>
。
好吧,想象一下如下所示的代码:
private List<ClientItem> ConvertToClientItems(BaseCollection<object> serverItems) {
serverItems.Add(new Buyer());
}
这应该编译,因为Buyer
是一个object
。
但是,如果您传递BaseCollection<Seller>
,您只是尝试将买家添加到卖家列表中。
因此,声明
BaseCollection<Seller>
是BaseCollection<object>
的一个亚型
仅当BaseCollection
确保泛型类型 T
仅用于输出位置时,才成立。上面的添加示例将在输入位置使用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. }
在 BaseCollection 中,您必须使用 "out" 关键字使 T 协变。
更多信息 http://msdn.microsoft.com/en-us/library/dd233059.aspx。
(IEnumerable 有效,因为它是协变的。
public interface BaseCollection<out T>