Hello,
here is some C# code that does not compile, giving the following message :
cannot convert from 'out T' to 'out Component'
public void Get<T>(out T c) where T : Component
{
m_components.TryGetValue(typeof(T), out c);
}
Here is code that does compile :
public void Get<T>(out T c) where T : Component
{
Component temp;
m_components.TryGetValue(typeof(T), out temp);
c = (T)temp;
}
I wonder why the first code is not valid since the "where T : Component" explicitly states that T is of type Component.
Thanks
-
I think the problem is in the out and it does not relate to Generics
we can produce the same error as follows
class A { } void fn(out object x) { x= new object(); } void main() { A x; fn(out x); //error } -
This is interesting.
I don't have an answer, but it's worth noting (to me, anyway), that the following works:
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:
(It's interesting because even if it's
out object tit's still not convertible betweenout Tandout object) -
It's because
outparameter types cannot be covariant/contravariant. The type of the variable must exactly match the parameter type.See:
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 }FlySwat : you beat me to it :(Chris Ballance : Nice explanation and example -
OK, I've figured it out:
What if you have the following:
public class BaseClass { ... } public class SubClass : BaseClass { ... }then I have the code:
Dictionary<int, BaseClass> comps; public void Get<T>(int num, out T c) where T : BaseClass { comps.TryGetValue(num, out c); }And I try to call it as thus:
SubClass sub; Get<SubClass>(1, out sub);Sub assume that the
BaseClasswith a key of 1 was actually aBaseClassand not aSubClass. Or Perhaps it isOtherSubClasswhereOtherSubClass : BaseClass -
I would guess that
TryGetValuelooks like :bool TryGetValue (Type someType, out Object result){ // do stuff// }thus
resultis anobjectrather thancomponentand cannot be implicitly converted, which is what you are trying to do. -
I'm going to take a shot at a more elaborate version of @Rex's answer and slightly corrected version of @Courtney's signature in that the type is Component, not object. Courtney's answer is basically right, just the types are a bit off.
bool TryGetValue(Type key, out Component result) { if (this.Contains(key)) { result = this[key]; // the type of result is Component! return true; } return false; }by passing T as the object type, you are trying to implicitly cast the base type Component to a subtype T. That is why your second example works. TryGetValue doesn't know about your Generic type T, it thinks everything in m_Components is a Component object.
This is a pretty common thing to get stuck thinking backwards. Because it's a parameter, not the return type, you get sucked into thinking it should work like any other parameter. However, because it's an out, it actually is better thought of as a return type for this purpose... it is going to try to assign the value of it's internal work to the parameter you provide.
0 comments:
Post a Comment