0

格納するオブジェクトに基づいて異なる実装を持つ次のクラスがあるとします。

public class ListOfPersistent<T> : 
    IList<T> where T : Persistent {... implementation ...}

public class ListOfNonPersistent<T> : 
     IList<T> {... implementation ...}

そして、次のようなことをして、上記のクラスで別のバージョンのいずれかを使用したいと思います。

public class PersistentList<T> : IList<T> {
  protected PersistentList() {
    if (list != null) {
      return;
    }

    if (Extensions.IsPersistent<T>()) {
      list = new ListOfPersistent<T>();

    } else {
      list = new ListOfNonPersistent<T>();
    }
  }

  protected IList<T> list;
  ....
}

もちろん、最初のクラスには型制約があり、2 番目のクラスには型制約がないため、上記はコンパイルされません。私ができる方法はありますか: この特定のケース ( list = new ListOfPersistent<T>()) の制約をチェックしないようにコンパイラーに伝えるか、コードが問題なくコンパイルされるように、共分散/反分散マジックを実行しますか?

4

1 に答える 1

1

IList<T>は不変であるため、ここでは共分散と反分散は役に立ちません。

個人的には、クラスの設計に欠陥があると主張します。a をインスタンス化してから、型が互換性のないListOfPersistent<T>変数に配置したくないはずです。IList<T>残念ながら、これらのクラスをどのように使用する予定であるか、全体的な目標が何であるかがわからないため、良い代替案を提案することはできません。しかし、それはハッキーであり、自分が何をしているのかを本当に知っている場合にのみ使用する必要があるという免責事項を付けて提案できます。

public static class ListUtils
{
    public static object CreateListOfPersistent(Type elementType)
    {
        if (!typeof(Persistent).IsAssignableFrom(elementType))
            throw new ArgumentException("elementType must derive from Persistent.", "elementType");
        var listType = typeof(ListOfPersistent<>).MakeGenericType(elementType);
        return Activator.CreateInstance(listType);
    }
}

// ...

if (Extensions.IsPersistent<T>())
    list = (IList<T>) ListUtils.CreateListOfPersistent(typeof(T));
else
    list = new ListOfNonPersistent<T>();
于 2011-01-27T23:20:24.233 に答える