Если я правильно прочитал ... тогда проблема в том, что только потому, что Foo : Bar
, это не означает, что ISomething<Foo> : ISomething<Bar>
...
В некоторых случаях вариант в C # 4.0 может быть вариантом. В качестве альтернативы, иногда есть вещи, которые вы можете сделать с помощью универсальных методов (хотя я не уверен, что это поможет).
Самое близкое, что вы можете сделать в C # 3.0 (и ниже), это, вероятно, неуниверсальный базовый интерфейс:
interface IFolderOrItem {}
interface IFolderOrItem<TFolderOrItem> : IFolderOrItem
where TFolderOrItem : FolderOrItem { }
обычно базовый интерфейс будет иметь, например, Type ItemType {get;}
для обозначения рассматриваемого реального типа. Тогда использование:
IFolderOrItem SelectedItem { get; set; }
...
public void SomeMagicMethod()
{
this.SelectedItem = GetMagicDocument(); // no cast needed
// not **so** bad
}
Из спецификации это относится к §25.5.6 (ECMA 334 v4):
25.5.6 Преобразования
Созданные типы следуют тем же правилам преобразования (§13)
как и неуниверсальные типы. При подаче заявления
эти правила, базовые классы и
интерфейсы сконструированных типов должны
быть определенным как описано в §25.5.3.
Никаких специальных преобразований между
построенные ссылочные типы, кроме
те, которые описаны в §13. Особенно,
в отличие от типов массивов, построенных
ссылочные типы не разрешают
ко-вариантные преобразования (§19.5). это
означает, что тип List<B>
не имеет
преобразование (неявное или
явно) до List<A>
, даже если B
получено из A
. Точно нет
существует преобразование из List<B>
в
List<object>
.
[Примечание: обоснование
это просто: если преобразование в
List<A>
разрешено, то, видимо,
можно хранить значения типа A
в
список. Однако это сломало бы
инвариант, что каждый объект в
список типа List<B>
всегда является значением
типа B
, или же неожиданные сбои
может произойти при назначении в
Коллекционные занятия. конечная нота]
То же самое относится и к интерфейсам. Это меняет бит в C # 4.0, но только в некоторых случаях.