无法从’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 T
和out object
之间转换)
我猜想TryGetValue
看起来像:
bool TryGetValue (Type someType, out Object result){ // do stuff// }
因此, result
是一个object
而不是component
,不能隐式转换,这是你想要做的。
- 为什么C#中的事件实现默认情况下不使用弱事件模式?
- LINQ如何查询值是否在范围列表之间?
- 获取Google广告ID并限制广告
- entity framework是否具有来自Linq2Sql(ObjectContext.CreateQuery ?)的等效DataContext.GetTable
- 使用reflection调用generics重载方法
- nHibernate Validator自定义IMessageInterpolator
- 使用TcpClient和Reactive Extensions从Stream读取连续字节流
- 一起添加两个DateTime对象
- 来自C#应用程序的ffmpeg使用Process类 – 用户提示符未显示在standardError中