输入参数,约束和协方差/逆变

时间:2011-01-27 22:58:48

标签: c# covariance variance

假设我有以下类,这些类具有基于要存储的对象的不同实现:

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;
  ....
}

当然上面没有编译,因为第一个类有一个类型约束而第二个类没有类型约束。有什么办法可以:告诉编译器它不应该检查这个特定情况下的约束(list = new ListOfPersistent<T>()),因为我知道它会属于那种类型,或者做一些协方差/逆变魔术,所以代码编译时没有任何问题?

1 个答案:

答案 0 :(得分:1)

协方差和逆变在这里对你没有帮助,因为IList<T>是不变的。

我个人认为你的班级设计存在缺陷。您不应该想要实例化ListOfPersistent<T>,然后将其放在类型IList<T>不兼容的变量中。不幸的是,我不能建议一个好的选择,因为我不知道你打算如何使用这些课程或你的总体目标是什么;但我可以通过免责声明 hacky 来提出 建议,如果您真的知道自己在做什么,我们应该只使用它:

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>();