无法从'out T'转换为'out Component'

noo*_*oon 9 c#

这里有一些不编译的C#代码,给出以下消息:

无法从'out T'转换为'out Component'

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

这是编译的代码:

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

我想知道为什么第一个代码无效,因为"where T:Component"明确指出T是Component类型.

谢谢

Rex*_*x M 13

这是因为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
}
Run Code Online (Sandbox Code Playgroud)


Jim*_*m L 4

我将尝试 @Rex 答案的更详细版本和 @Courtney 签名的稍微更正版本,因为类型是组件,而不是对象。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;
}
Run Code Online (Sandbox Code Playgroud)

通过将 T 作为对象类型传递,您试图将基本类型 Component隐式转换为子类型 T。这就是第二个示例有效的原因。TryGetValue 不知道您的泛型类型 T,它认为 m_Components 中的所有内容都是 Component 对象。

陷入逆向思维是很常见的事情。因为它是一个参数,而不是返回类型,所以您会陷入认为它应该像任何其他参数一样工作的情况。但是,因为它是一个out,所以实际上最好将其视为为此目的的返回类型......它将尝试将其内部工作的值分配给您提供的参数。