简体   繁体   English

类型参数,约束和协方差/协方差

[英]Type parameters, constraints and covariance/contravariance

Let's say I have the following classes that have different implementations based on the object to be stored in: 假设我有以下类,这些类根据要存储的对象具有不同的实现:

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

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

And I want to use one of another version on the above classes by doing something like this: 我想通过做这样的事情在上述类中使用另一个版本:

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

Of course the above does not compiles, because there is a type constrain on the first class and none on the second. 当然,以上内容不会编译,因为在第一类上没有类型约束,在第二类上没有类型约束。 Is there any way I can: Tell the compiler that it should not check the constrain on this specific case ( list = new ListOfPersistent<T>() ) because I KNOW it will be of that type, or do some covariance/contravariance magic so the code compiles without any issues? 有什么办法可以告诉我:告诉编译器它不应该检查这种特定情况下的约束( list = new ListOfPersistent<T>() ),因为我知道它将是这种类型,或者做一些协方差/协方差魔术,所以代码编译没有任何问题?

Covariance and contravariance won't help you here because IList<T> is invariant. 因为IList<T>是不变的,所以协方差和协变对您无济于事。

Personally I would argue that you have a flaw in your class design. 我个人认为您的班级设计有缺陷。 You shouldn't want to instantiate a ListOfPersistent<T> and then place it in a variable whose type, IList<T> , is incompatible. 您不希望实例化ListOfPersistent<T> ,然后将其放在类型IList<T>不兼容的变量中。 Unfortunately I cannot suggest a good alternative because I have no idea how you are planning to use these classes or what your overall goal is; 不幸的是,由于我不知道您打算如何使用这些类或您的总体目标是什么,我无法提出一个好的选择。 but I can make a suggestion with a disclaimer that it is hacky and should probably only be used if you really know what you are doing: 但我可以用一个声明,这是哈克 ,应该大概只有当你真的知道你在做什么使用建议:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM