回归泛型类型

时间:2013-06-03 12:29:49

标签: c# generics casting

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

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

2 个答案:

答案 0 :(得分:3)

您的通用语的约束条件是DbTransactionType必须是类DbTransaction 或从中派生的任何类

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

但如果不清楚: BeginTransaction的返回值是类型DbTransaction的实例。 _transaction的类型为DbTransactionType,可以是DbTransaction子类。您无法在不进行强制转换的情况下将基类的变量分配给子类的变量。只有当基类的变量实际包含该子类的实例时,强制转换才会起作用。

在考虑此问题时,在您的心智模型中,将DbTransactionType替换为string,将DbTransaction替换为object。现在问题应该立即变得明确。

答案 1 :(得分:3)

您只需将DbTransactionType限制为DbTransaction 或任何子类,只要该类型具有无参数构造函数即可。因此,虽然您可以使用任何子类代替DbTransaction,但在另一个方向上不是这样,DbTransactionType可以引用这样的子类,从而使DbTransaction的赋值成为问题。