这里有一些不编译的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)
我将尝试 @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,所以实际上最好将其视为为此目的的返回类型......它将尝试将其内部工作的值分配给您提供的参数。