не удается конвертировать из 'Т' К 'из'

вот некоторый код C#, который не компилируется, давая следующее сообщение:

не удается преобразовать из' out T 'в' out Component'

    public void Get<T>(out T c) where T : Component
    {
        m_components.TryGetValue(typeof(T), out c);
    }

вот код, который компилируется :

    public void Get<T>(out T c) where T : Component
    {
        Component temp;
        m_components.TryGetValue(typeof(T), out temp);
        c = (T)temp;
    }

интересно, почему первый код недействителен с "где T : компонент" явно указывает, что T имеет тип Component.

спасибо

6 ответов


Я собираюсь выстрелить в более сложную версию ответа @Rex и слегка исправленную версию подписи @Courtney в том, что тип является компонентом, а не объектом. Ответ Кортни в основном прав, просто типы немного не в себе.

bool TryGetValue(Type key, out Component result)
{
       if (this.Contains(key))
       {
           result = this[key]; // the type of result is Component!
           return true;
       }

      return false;
}

передавая T как тип объекта, вы пытаетесь имплицитно приведите компонент базового типа к подтипу T. вот почему ваш второй пример работает. TryGetValue не знает о вашем общем типе T, он думает все в m_Components является компонентным объектом.

Это довольно распространенная вещь, чтобы застрять, думая назад. Поскольку это параметр, а не тип возврата, вы втягиваетесь в мысль, что он должен работать как любой другой параметр. Однако, потому что это out, это на самом деле лучше думать как тип возврата для этой цели... он попытается присвоить значение своей внутренней работы параметру, который вы предоставляете.


потому что out типы параметров не может быть ковариантные/контравариантным. тип переменной должен совпадать с типом параметра.

посмотреть:

class Super { }
class Sub : Super { }

void Test(out Super s)
{
    s = new Super();
}

void Main()
{
    Sub mySub = new Sub();
    Test(out mySub); //doesn't work
}

Я думаю, что проблема в из и это не относится к дженерикам

мы можем произвести такую же ошибку следующим образом

class A
{
}

void fn(out object x)
{
 x= new object();
}
void main()
{
 A x;
fn(out x); //error
}

хорошо, я понял:

Что делать, если у вас есть следующие:

 public class BaseClass { ... }
 public class SubClass : BaseClass { ... }

тогда у меня есть код:

 Dictionary<int, BaseClass> comps;

 public void Get<T>(int num, out T c) where T : BaseClass
 {
     comps.TryGetValue(num, out c);
 }

и я пытаюсь назвать это так:

 SubClass sub;
 Get<SubClass>(1, out sub);

Sub предположим, что BaseClass С ключом 1 был на самом деле BaseClass, а не SubClass. Или, возможно, это OtherSubClass здесь OtherSubClass : BaseClass


Это интересно.

у меня нет ответа, но стоит отметить (для меня, во всяком случае), что работает следующее:

    public void M<T> (out T c) where T : Test
    {
        // Test m;
        // A(out m);
        // c = (T) m;

        A(out c);
    }

    public void A<T> (out T t) where T : Test
    {
        t = null;
    }

-- Edit:

(Это интересно, потому что даже если это out object t он все еще не конвертируется между out T и out object)


Я бы предположил, что TryGetValue выглядит так :

bool TryGetValue (Type someType, out Object result){ 
   // do stuff//
}
result это object, а не component и не может быть неявно преобразован, что вы пытаетесь сделать.