2

これが私が直面しているシナリオです:

public abstract class Record { }

public abstract class TableRecord : Record { }

public abstract class LookupTableRecord : TableRecord { }

public sealed class UserRecord : LookupTableRecord { }

public abstract class DataAccessLayer<TRecord> : IDataAccessLayer<TRecord>
    where TRecord : Record, new() { }

public abstract class TableDataAccessLayer<TTableRecord> : DataAccessLayer<TTableRecord>, ITableDataAccessLayer<TTableRecord>
    where TTableRecord : TableRecord, new() { }

public abstract class LookupTableDataAccessLayer<TLookupTableRecord> : TableDataAccessLayer<TLookupTableRecord>, ILookupTableDataAccessLayer<TLookupTableRecord>
    where TLookupTableRecord : LookupTableRecord, new() { }

public sealed class UserDataAccessLayer : LookupTableDataAccessLayer<UserRecord> { }

public interface IDataAccessLayer<TRecord>
    where TRecord : Record { }

public interface ITableDataAccessLayer<TTableRecord> : IDataAccessLayer<TTableRecord>
    where TTableRecord : TableRecord { }

public interface ILookupTableDataAccessLayer<TLookupTableRecord> : ITableDataAccessLayer<TLookupTableRecord>
    where TLookupTableRecord : LookupTableRecord { }

さて、次のキャストを実行しようとすると、コンパイルされません。

UserDataAccessLayer udal = new UserDataAccessLayer();
            ITableDataAccessLayer<TableRecord> itdal = (ITableDataAccessLayer<TableRecord>)udal;

ただし、次のキャストを実行すると、ランタイムエラーなしでコンパイルされます。

UserDataAccessLayer udal = new UserDataAccessLayer();
            ITableDataAccessLayer<UserRecord> itdal = (ITableDataAccessLayer<UserRecord>)udal;

ITableDataAccessLayer<TableRecord>具体的なタイプがわからないので、ベースインターフェイスを操作する必要があります。

これが私の質問に答えるのに十分説明的で役立つことを願っています。

4

3 に答える 3

5

実行しようとしていることは、.NET 4.0ではサポートされていますが、3.5ではサポートされていません。これは、一般的な共分散と呼ばれます。その間に代わりにできることは、ITableDataAccessLayerと呼ばれる非ジェネリックインターフェイスを作成し(Tを使用する場合は常にObject型を使用)、明示的なインターフェイス実装を提供することです。これは、.NETで処理するジェネリック型の数です。

于 2009-11-22T07:46:31.727 に答える
4

確かに、共分散が必要です。カップルポイント。

まず、なぜこれが違法でなければならないのかを理解してください。IListを例にとってみましょう。IList<Giraffe>キリンのリストがあるとします。それを動物のリストに変換できますか?いいえ、安全ではありません。はい、キリンのリストは、リスト内のすべてが動物であるという意味での動物のリストです。ただし、リストは変更可能です。トラを動物のリストに貼り付けることはできますが、それが本当にキリンのリストである場合、これは失敗する必要があります。これは安全ではないため、C#4ではIListを共変にしません。

次に、このトピックに興味がある場合は、型の安全性を維持するために機能がどのように設計されているかについての私の長い一連のブログ記事を読むことをお勧めします。

http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx

第三に、参考までに、インターフェースが安全に共変または反変になる可能性がある場合に計算するために使用する正確なルールを、今後数週間でブログに投稿します。

于 2009-11-22T17:06:41.537 に答える
0

これはコンパイルされますか?

UserDataAccessLayer udal = new UserDataAccessLayer(); 
ITableDataAccessLayer<TTableRecord> itdal = (ITableDataAccessLayer<TTableRecord>)udal;

または単に

ITableDataAccessLayer<TTableRecord> itdal = new UserDataAccessLayer(); 

これは汎用インターフェースなので、おそらくそれがどのタイプであるかを知る必要がありますか?

エラーメッセージも知っておくと役に立ちます。それは通常、主題に光を当てます。

于 2009-11-22T07:45:15.800 に答える