2

假设以下示例。数据库连接处理的通用方法。 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”。存在显式转换(您是否缺少演员表?)

我当然可以施放它,但问题是为什么

4

2 回答 2

3

你的泛型有一个约束,说它DbTransactionType需要是类DbTransaction 或从它派生的任何类

有了这个亮点,应该清楚的是你甚至不应该明确地投射它。

但是如果不清楚的话:返回值BeginTransaction是 type 的一个实例DbTransaction。的类型可以是_transaction类。如果不进行强制转换,就不能将基类的变量分配给子类的变量。只有当基类的变量实际上包含该子类的实例时,强制转换才会起作用。DbTransactionTypeDbTransaction

当考虑这个问题时,在你的心智模型中替换DbTransactionTypestring和。现在问题应该立即变得清晰。DbTransactionobject

于 2013-06-03T12:32:59.750 回答
3

只要类型具有无参数构造函数,您只需限制DbTransactionTypeDbTransaction 或任何子类。因此,虽然您可以使用任何子类代替DbTransaction相同的子类,但在另一个方向上是不正确的,并且DbTransactionType可以引用这样的子类,从而使分配有DbTransaction问题。

于 2013-06-03T12:33:11.140 回答