基本オブジェクトを汎用関数のパラメーターとして使用する
-
05-07-2019 - |
質問
ジェネリックを使用してヘルパーメソッドを実装しようとしています(C#/ 3.5) クラスの構造は素晴らしく、基本クラスは次のようになっています。
public class SomeNiceObject : ObjectBase
{
public string Field1{ get; set; }
}
public class CollectionBase<ObjectBase>()
{
public bool ReadAllFromDatabase();
}
public class SomeNiceObjectCollection : CollectionBase<SomeNiceObject>
{
}
そして、次のような一般的な方法を使用してコレクションを取得します。
public class DAL
{
public SomeNiceObjectCollection Read()
{
return ReadFromDB<SomeNiceObjectCollection>();
}
T ReadFromDB<T>() where T : CollectionBase<ObjectBase>, new()
{
T col = new T();
col.ReadAllFromDatabase();
return col;
}
}
これはビルドされません、
Error 66 The type 'SomeNiceObjectCollection' cannot be used as type parameter 'T' in the generic type or method 'ReadFromDB<T>'. There is no implicit reference conversion from 'SomeNiceObjectCollection' to 'CollectionBase<ObjectBase>'.
SomeNiceObjectCollectionオブジェクトは、正確にはCollectionBaseであるCollectionBaseです。どうすればこれを機能させることができますか?
解決
C#はリストタイプ間のキャスト(共分散)をサポートしていません。
このパターンをサポートする最善の方法は、汎用コレクションに依存しないように、ReadAllFromDatabaseメソッドのインターフェイスを導入することです。
public class SomeNiceObject : ObjectBase
{
public string Field1{ get; set; }
}
public interface IFromDatabase
{
bool ReadAllFromDatabase();
}
public class CollectionBase<ObjectBase>() : IFromDatabase
{
public bool ReadAllFromDatabase();
}
public class SomeNiceObjectCollection : CollectionBase<SomeNiceObject>
{
}
public class DAL
{
public SomeNiceObjectCollection Read()
{
return ReadFromDB<SomeNiceObjectCollection>();
}
T ReadFromDB<T>() where T : IFromDatabase, new()
{
T col = new T();
col.ReadAllFromDatabase();
return col;
}
}
他のヒント
C#3.0ではこれは不可能ですが、C#および.NET 4.0では共分散と反分散が可能なため、これが可能になる可能性があります。
考えてみましょう。派生オブジェクトを含むコレクションを取得し、一時的にベースオブジェクトのコレクションとして処理しようとしています。これが許可されている場合は、派生オブジェクトではないベースオブジェクトをリストに挿入できます。
ここでは、例:
List<String> l = new List<String>();
List<Object> o = l;
l.Add(10); // 10 will be boxed to an Object, but it is not a String!
所属していません StackOverflow