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サブクラスになるDbTransactionType可能性があります。キャストせずに、基本クラスの変数をサブクラスの変数に割り当てることはできません。また、キャストは、基本クラスの変数に実際にそのサブクラスのインスタンスが含まれている場合にのみ機能します。DbTransaction

この問題について考えるときは、メンタル モデルDbTransactionTypestringDbTransactionを に置き換えますobject。これで、問題はすぐに明らかになるはずです。

于 2013-06-03T12:32:59.750 に答える
3

型にパラメーターなしのコンストラクターがある限り、または任意のサブクラスに制限するだけDbTransactionTypeです。そのため、代わりに任意のサブクラスを使用できますが、同じことは他の方向には当てはまらず、そのようなサブクラスを参照する可能性があるため、問題のある割り当てが行われます。DbTransaction DbTransactionDbTransactionTypeDbTransaction

于 2013-06-03T12:33:11.140 に答える