2009-12-03 12 views
9

qui è un codice C# che non si compila, dando il seguente messaggio:non può convertire da 'fuori T' a 'out Component'

non può convertire da 'fuori T' a 'out Component'

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

Ecco codice che fa compilare:

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

mi chiedo perché il primo codice non è valido dal "dove T: Componente" afferma esplicitamente che T è di tipo Componente.

Grazie

+0

Perché dovresti rendere "Get " un metodo generico se T è definito come di tipo Componente? Forse sei un paradiso, hai menzionato lo scenario esatto qui. –

+3

* twiddles thumbs in attesa che Mr. Skeet ci illumini su questo problema intrigante * – tster

+0

Questo è un duplicato. http://stackoverflow.com/questions/1207144/c-why-doesnt-ref-and-out-support-polymorphism/1207302#1207302 –

risposta

4

Ho intenzione di scattare una versione più elaborata della risposta di @ Rex e una versione leggermente corretta della firma di @ Courtney in quanto il tipo è Componente, non oggetto. La risposta di Courtney è fondamentalmente corretta, solo i tipi sono un po 'spenti.

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

     return false; 
} 

passando T come il tipo di oggetto, si sta tentando di implicitamente gettato il tipo di base dei componenti ad un T. sottotipo che è il motivo per cui il tuo secondo esempio funziona. TryGetValue non conosce il tuo tipo generico T, pensa che tutto in m_Components sia un oggetto Component.

Questa è una cosa abbastanza comune per rimanere bloccati a pensare all'indietro. Poiché si tratta di un parametro, non del tipo restituito, si viene risucchiati a pensare che dovrebbe funzionare come qualsiasi altro parametro. Tuttavia, poiché è uno , in realtà è meglio pensarlo come un tipo di ritorno per questo scopo ... cercherà di assegnare il valore del suo lavoro interno al parametro che fornisci.

3

Credo che il problema è nella fuori e non si riferisce alla Generics

siamo in grado di produrre lo stesso errore come segue

class A 
{ 
} 

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

Questo è interessante.

Non ho una risposta, ma vale la pena notare (per me, comunque), che le seguenti opere:

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:

(E 'interessante perché, anche se si tratta di out object t è ancora trasformabili tra out T e out object)

12

è perché out tipi di parametri non possono essere covariant/contravariant. Il tipo della variabile deve corrispondere esattamente al tipo di parametro.

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

mi hai battuto :( – FlySwat

+0

Bella spiegazione ed esempio –

0

OK, ho calcolato fuori:

Cosa fare se avete il seguente:

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

allora ho il codice:

Dictionary<int, BaseClass> comps; 

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

Un d provo a chiamarlo come così:

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

Sub supporre che il BaseClass con una chiave di 1 era in realtà un BaseClass e non un SubClass.O forse è OtherSubClass dove OtherSubClass : BaseClass

-2

Direi che TryGetValue assomiglia:

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

così result è un object piuttosto che component e non può essere implicitamente convertito, che è quello che sta cercando di fare.

Problemi correlati