Введите параметры, ограничения и ковариацию / контравариантность - PullRequest
0 голосов
/ 28 января 2011

Допустим, у меня есть следующие классы, которые имеют разные реализации, основанные на объекте, который будет храниться:

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 Ответ

1 голос
/ 28 января 2011

Ковариация и контравариантность здесь вам не помогут, потому что 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>();
...