对泛型类型进行反类型转换
本文关键字:类型转换 泛型类型 | 更新日期: 2023-09-27 18:16:29
假设如下示例:处理数据库连接的通用方法。DbConnection.BeginTransaction()
(来自System.Data.Common)返回一个DbTransaction
实例。既然这是显式声明的,为什么我需要显式转换它呢?
internal abstract class ADatabase<DbCommandType, DbConnectionType, DbTransactionType> : IDisposable
where DbCommandType : DbCommand, new()
where DbConnectionType : DbConnection, new()
where DbTransactionType : DbTransaction, new()
{
DbConnectionType _connection;
DbTransactionType _transaction;
void Foo()
{
_transaction = _connection.BeginTransaction(); // <-- Error..
}
}
得到的错误是
错误1无法隐式转换类型"System.Data.Common"。从"DbTransaction"到"DbTransactionType"。存在显式转换(您是否缺少强制类型转换?)
当然可以强制转换,但问题是为什么要?
你的泛型有一个约束,说DbTransactionType
需要是类DbTransaction
或从它派生的任何类。
有了这个高亮显示,应该很清楚,你甚至不应该显式地强制转换它。
但如果不清楚:BeginTransaction
的返回值是DbTransaction
类型的实例。_transaction
的类型为DbTransactionType
,可能是DbTransaction
的子类。不进行强制类型转换,就不能将基类的变量赋值给子类的变量。只有当基类的变量实际上包含该子类的实例时,强制类型转换才会起作用。
思考这个问题时,在你的心智模型中将DbTransactionType
替换为string
,将DbTransaction
替换为object
。现在问题应该马上就清楚了。
您只需将DbTransactionType
限制为DbTransaction
或任何子类,只要该类型具有无参数构造函数。因此,虽然您可以使用任何子类来代替DbTransaction
,但在另一个方向上并非如此,DbTransactionType
可以引用这样的子类,从而使DbTransaction
的分配有问题。