2015-11-25 4 views
0

Я хочу, чтобы иметь возможность отличать класс с общим типом (который является другим интерфейсом с общим типом) к его интерфейсу, но генерируется исключение.Вставить в интерфейс с вложенным типом интерфейса с общим

Я могу отличить объект с универсальным типом к его интерфейсу (см. Строку IWrapper ....), но когда я пытаюсь выполнить литье с интерфейсом как тип с собственным родовым типом, я получаю ошибку.

Мои мысли в том, что, возможно, мне нужно будет добавить ограничение типа к типу узла, которое должно быть IWrapper<U>, но затем оно больше не является общим.

Несомненно, если объект имеет тип Node<Wrapper<object>, где интерфейсы интерфейса узла и обертки, тогда литье в INode<IWrapper<object>> должно работать нормально?

Вот мой SSCEE:

namespace Test 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Wrapper<object> wrapper = new Wrapper<object>(); 
      IWrapper<object> castedWrapper = (IWrapper<object>)wrapper; // Works fine 

      var node = new Node<object>(); 
      node.Value = wrapper; 

      INode<IWrapper<object>> castedNode = (INode<IWrapper<object>>)node; 
      // Unable to cast object of type 'Test.Node`1[System.Object]' to type 'Test.INode`1[Test.IWrapper`1[System.Object]]'. 
     } 
    } 
    class Node<T> : INode<T> 
    { 
     public INode<T> Parent { get; set; } 
     public T Value { get; set; } 
    } 

    class Wrapper<U> : IWrapper<U> 
    { 
     public U WrappedValue { get; set; } 
    } 

    interface INode<T> 
    { 
     INode<T> Parent { get; set; } 
     T Value { get; set; } 
    } 

    interface IWrapper<U> 
    { 
     U WrappedValue { get; set; } 
    } 

} 
+2

Try маркировки INode как '' INode поэтому общий параметр ковариантен (в интерфейсе decleration) – BradleyDotNET

+0

@BradleyDotNET спасибо, теперь я получаю сообщение об ошибке: 'Invalid дисперсии: тип параметра«T»должен быть контрвариантно действительным на 'INode .Parent'. 'T' является ковариантным. ' – mbdavis

+0

В Covariance есть несколько очень специфических правил, очевидно, что вы их нарушаете. Ваш листинг/ковариация не будет действителен до тех пор, пока вы не принесете ее с помощью https://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx – BradleyDotNET

ответ

0

Здесь вы делаете несколько вещей неправильно. Позвольте удалить var и посмотреть, что происходит.

Node<object> node = new Node<object>(); 
node.Value = wrapper; 

Это ясно, что Node<Object> не типа Node<IWrapper<object>>. Вот почему вы получаете ошибку. Поскольку ограничений для T или U нет, вы можете сделать что-то вроде литья Node<Object> до Node<int>, что явно не допускается на C#.

Может быть, вы должны объявить узел как:

Node<IWrapper<object>> node = new Node<IWrapper<object>>(); 
node.Value = wrapper; 

Теперь ниже должна работать идеально.

INode<IWrapper<object>> castedNode = (INode<IWrapper<object>>)node; 

Для предотвращения таких ошибок следует использовать общие ограничения.

+0

ах, просто. ура! – mbdavis

Смежные вопросы