2011-02-02 15 views
5

Ho le seguenti classi e sto provando a chiamare Confronto metodo dalla classe ExportFileBaseBL ma ottengo l'erroreC# Generics - Richiamo metodo generico da una classe generica

Impossibile convertire implicitamente il tipo 'Class1' a 'T' . Esiste una conversione esplicita (che le manca un cast?)

public abstract class Class1<T> where T: Class2 
{ 
    public abstract Class1<T> Compare(Class1<T> otherObj); 
} 

public abstract class Class3<T, U> where T: Class1<U> 
         where U: Class2 
{ 
    public T Compare(T obj1, T obj2) 
    { 
     if (obj1.Prop1 > obj2.Prop1) 
     { 
      return obj1.Compare(obj2); // Compiler Error here 
     } 
     else 
     { 
      return obj2.Compare(obj1); // Compiler Error here 
     } 
    } 

} 

Non dovrebbe la conversione di tipo implicita? Mi sto perdendo qualcosa?

risposta

4

Il problema è che il metodo astratto Compare è definito per accettare un parametro di tipo Class1<T> e restituire un istanza di Class1<T>, non un più specifico tipo di Class1<T>. Ma questo è ciò che il tuo metodo Class3.Compare sta tentando di fare: chiamare T.Compare e assumere che l'output sarà un T, quando in realtà puoi solo essere sicuro che sarà un Class1<U>.

per offrire un esempio più comprensibile semplice, supponiamo che ho avuto questa classe:

class Parser 
{ 
    public abstract object Parse(string text); 
} 

class Int32Parser 
{ 
    public int Parse(Parser parser, string text) 
    { 
     return parser.Parse(text); 
    } 
} 

Il codice di cui sopra fa un presupposto errato simile al vostro: che parser.Parse restituirà una int solo perché int deriva da object (come nel tuo caso, T deve derivare da Class1<U>); infatti, puoi solo essere sicuro che restituirà un object.

Ci sono due modi che posso vedere per risolvere questo problema: fare Class1<T>.Compare un metodo generico:

public abstract U Compare<U>(U otherObj) where U : Class1<T>; 

... o rilassarsi al tipo specificità del valore di ritorno il tuo metodo di Class3.Compare:

public Class1<U> Compare(T obj1, T obj2) 
{ 
    // ... 
} 

Personalmente, preferirei il secondo a meno che non sia assolutamente necessario il primo. Tutti questi vincoli di tipo generico possono diventare molto disordinati e sovraccaricarsi di più di quanto ci si aspetti quando la complessità inizia a crescere in questo modo.

+0

Grazie Dan, che risponde alla mia domanda. – logik6

+0

Jup jup, ora che abbiamo aggiunto un aggiornamento sulla digitazione del metodo di confronto sono d'accordo con la risposta. – jcolebrand

2

Chiama il metodo con il tipo di parametro che dichiari a livello di classe.

return obj1.Compare<T>(obj2); 

Avrai bisogno di fare la definizione del metodo Compare generica così:

public abstract Class1<T> Compare<T>(Class1<T> otherObj); 
+1

Il metodo Compare non è generico, quindi non accetta un parametro di tipo nella sua forma corrente. –

+0

Ma @Kyle che illustra semplicemente dove deve essere corretto nel codice padre. Deve anche aggiungere un '' al primo metodo di confronto di classe. – jcolebrand

+0

Questo dovrebbe essere aggiunto alla risposta quindi. Lo aggiungerò –

Problemi correlati