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

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

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

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

这是编译的代码:

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

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

谢谢

我将拍摄一个更精细版本的@Rex的答案以及@Courtney签名的略微修正版本,因为类型是Component,而不是对象。 考特尼的答案基本上是正确的,只是类型有点偏。

 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作为对象类型传递,您尝试将基类型Component 式转换为子类型T.这就是您的第二个示例有效的原因。 TryGetValue不知道您的Generic类型T,它认为m_Components中的所有内容都是Component对象。

这是一个很常见的事情,让你陷入困境。 因为它是一个参数,而不是返回类型,所以你会觉得它应该像任何其他参数一样工作。 但是,因为它是一个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 } 

我认为问题外面 ,它与generics无关

我们可以产生如下相同的错误

 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 comps; public void Get(int num, out T c) where T : BaseClass { comps.TryGetValue(num, out c); } 

我试着这样称呼它:

  SubClass sub; Get(1, out sub); 

Sub假设键为1的BaseClass实际上是BaseClass而不是SubClass 。 或者也许是OtherSubClass : BaseClass

这是有趣的。

我没有答案,但值得注意的是(无论如何),以下是有效的:

  public void M (out T c) where T : Test { // Test m; // A(out m); // c = (T) m; A(out c); } public void A (out T t) where T : Test { t = null; } 

– 编辑:

(这很有趣,因为即使它out object t它仍然无法在out Tout object之间转换)

我猜想TryGetValue看起来像:

 bool TryGetValue (Type someType, out Object result){ // do stuff// } 

因此, result是一个object而不是component ,不能隐式转换,这是你想要做的。