2010-06-14 7 views
6

Il seguente codice non compila (error CS0123: No overload for 'System.Convert.ToString(object)' matches delegate 'System.Converter<T,string>'):In che modo la risoluzione di sovraccarico del gruppo metodo è diversa dalla risoluzione di sovraccarico chiamata metodo?

class A<T> { 
    void Method(T obj) { 
     Converter<T, string> toString = Convert.ToString; 

     // this doesn't work either (on .NET 4): 
     Converter<object, string> toString2 = Convert.ToString; 
     Converter<T, string> toString3 = toString2;    
    } 
} 

Tuttavia, questo:

class A<T> { 
    void Method(T obj) { 
     // o is a T, and Convert.ToString(o) is using 
     // string Convert.ToString(object o) 

     Converter<T, string> toString = o => Convert.ToString(o); 
    } 
} 

In C# 4, delegati co/contra-variante può essere assegnato a vicenda, e i delegati possono essere creati da metodi co/contra-variant, quindi il metodo ToString(object) può essere utilizzato come Converter<T, string>, poiché T è sempre garantito per essere convertito in un object.

Quindi, il primo esempio (risoluzione di sovraccarico del gruppo metodo) dovrebbe trovare l'unico metodo applicabile string Convert.ToString(object o), lo stesso della risoluzione di sovraccarico chiamata metodo. Perché il metodo metodo & metodo di risoluzione di sovraccarico chiamata produce risultati diversi?

risposta

3

Questo ha a che fare con il fatto che la varianza non è applicabile ai tipi di valore, quindi se si limita T come where T : class si ottiene la varianza sulla T e il primo frammento di codice verrà compilato.

Dal Covariance and Contravariance FAQ:

varianza è supportata soltanto se un parametro di tipo è un tipo di riferimento. La varianza non è supportata per i tipi di valore .

+0

Più precisamente, si tratta di non lavorare per un non vincolato 'T' perché _might be_ un tipo di valore. – thecoop

0

Il secondo codice compilato perché oderiva da object, quindi ovviamente è possibile richiamare un metodo che accetta un object come input con qualsiasi tipo di parametro.

I tipi di delegato, tuttavia, sono non uguale a. A meno che lo T sia object, le firme del metodo non corrispondono. Se, per esempio, T è int, si otterrebbe un Converter<int, string> che non è lo stesso di Converter<object, string. Sono due interamente diversi tipi.

Stai riscontrando i problemi relativi alla mancanza di co/contro-varianza del C# 3.0. Dovrebbe essere meglio in C# 4.

+0

Questo è in .NET 4. Ho aggiornato la mia domanda – thecoop