2009-12-03 18 views
9

Oto niektóre kodu C#, które nie kompiluje, podając następujący komunikat:nie można przekonwertować z „out T” do „z komponentu”

nie można przekonwertować z „out T” do „z komponentu”

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

Oto kod, który robi kompilacji:

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

zastanawiam się, dlaczego pierwszy kod nie jest poprawny ponieważ "gdzie T: składnik" wyraźnie stwierdza, że ​​T jest typu Komponent.

Dzięki

+0

Dlaczego konieczne jest wykonanie "Uzyskaj " jako ogólnej metody, jeśli T jest zdefiniowane jako typ Komponent? Być może jesteś tu, o tym miejscu nie wspominałeś. –

+3

* Twiddles kciuki czekają na pana Skeeta, aby oświecić nas w tym intrygującym numerze * – tster

+0

To jest duplikat. http://stackoverflow.com/questions/1207144/c-why-doesnt-ref-and-out-support-polymorphism/1207302#1207302 –

Odpowiedz

4

Zamierzam zrobić zdjęcie w bardziej rozbudowanej wersji odpowiedzi @ Rexa i nieco poprawionej wersji sygnatury @ Courtney, ponieważ typem jest Komponent, a nie obiekt. Odpowiedź Courtney jest w zasadzie słuszna, tylko typy są nieco nietypowe.

bool TryGetValue(Type key, out Component result) 
{ 
     if (this.Contains(key)) 
     { 
      result = this[key]; // the type of result is Component! 
      return true; 
     } 

     return false; 
} 

przekazując T jako typ obiektu, który próbujesz niejawnie rzutować typ bazowy komponent do podtypu T. Oznacza to dlaczego drugi przykład działa. TryGetValue nie wie o twoim typie ogólnym T, uważa, że ​​wszystko w m_Components jest obiektem Component.

To jest dość powszechna rzecz, aby utknąć myśląc wstecz. Ponieważ jest to parametr, a nie typ zwracany, zostajesz zassany do myślenia, że ​​powinien działać jak każdy inny parametr. Jednakże, ponieważ jest to obecnie, w rzeczywistości jest lepiej pomyślany jako typ zwrotu w tym celu ... będzie próbował przypisać wartość jego pracy wewnętrznej do podanego parametru.

3

Myślę, że problem jest w zewnątrz i nie odnoszą się do rodzajowych

możemy produkować ten sam błąd co następuje

class A 
{ 
} 

void fn(out object x) 
{ 
x= new object(); 
} 
void main() 
{ 
A x; 
fn(out x); //error 
} 
-2

To jest ciekawe.

nie mam odpowiedzi, ale warto zauważyć, (dla mnie w każdym razie), że następujące utwory:

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; 
    } 

- Edycja:

(To ciekawe, bo nawet jeśli jest to out object t to jeszcze nie wymienialne między out T i out object)

12

to dlatego out typy parametrów nie może być covariant/contravariant. Typ zmiennej musi dokładnie odpowiadać typowi parametru.

Patrz:

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 
} 
+0

pokonałeś mnie :( – FlySwat

+0

Dobre wyjaśnienie i przykład –

0

OK, ja zorientowaliśmy się:

Co jeśli masz następujące:

public class BaseClass { ... } 
public class SubClass : BaseClass { ... } 

potem mam kod:

Dictionary<int, BaseClass> comps; 

public void Get<T>(int num, out T c) where T : BaseClass 
{ 
    comps.TryGetValue(num, out c); 
} 

An d próbuję to nazwać jako sposób:

SubClass sub; 
Get<SubClass>(1, out sub); 

zakładać Sub że BaseClass z kluczem 1 był rzeczywiście BaseClass a nie SubClass.A może to jest OtherSubClass gdzie OtherSubClass : BaseClass

-2

Przypuszczam, że TryGetValue wygląda następująco:

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

zatem result jest object zamiast component i nie można niejawnie konwertowane, co jest, co chce robić.

Powiązane problemy