2013-03-12 9 views
5

Ho incontrato un problema con metodi di overload che hanno vincoli diversi che sembrano esclusivi. Questo è il mio esempio:Membro con la stessa firma già definita con diversi vincoli di tipo

public class A 
{ 
    public void Do<T>() where T : class 
    { 

    } 

    public void Do<T>() where T : struct 
    { 

    } 
} 

E questo non si compila con il seguente errore "Stati con la stessa firma già definito". È possibile soddisfare entrambe le condizioni contemporaneamente o è solo la limitazione del compilatore C#?

risposta

8

Non è una limitazione del compilatore - è una limitazione del lingua (e molto probabilmente il CLR pure; io non sono sicuro).

Fondamentalmente si tratta di sovraccarichi che si scontrano: è come cercare di sovraccaricare per tipo di ritorno. Non è supportato

E è possibile dichiarare i metodi in modo tale che queste chiamate compilati correttamente alle invocazioni di metodi diversi:

a.Do<int>(); 
a.Do<string>(); 
a.Do<int?>(); 

... ma si tratta sempre parametri opzionali e/o array di parametri, ed è horrible.

Si noti inoltre che, anche se non si può sovraccaricare da vincoli generici, si possibile sovraccarico dal "arietà" generico (il numero di parametri di tipo):

public void Foo() {} 
public void Foo<T>() {} 
public void Foo<T1, T2>() {} 
+0

Almeno spero che era corretto dire che questi due vincoli sono esclusivi ed è solo la limitazione , destra? :) –

+0

@IlyaChernomordik: È un limite, ma un IMO piuttosto ragionevole. –

+0

Ma cosa c'è di sbagliato nel permettere questo? Devo solo fare diverse azioni a seconda che si tratti di una classe (posso verificare se è nulla) o quando è solo lunga (allora so che il valore è lì). Quindi la via d'uscita dovrebbe semplicemente dare nomi diversi ai metodi che sembra. Io sicuramente non voglio usare il modo orribile :) –

2

Non si può sovraccaricare un metodo per varing il parametro generico contiene. Per un overload di metodo valido è necessario avere parametri di input diversi per il metodo.

1

Entrambi i metodi dovrebbero avere il seguente nome quando viene compilato:

A.Do``1 

Come il conteggio dei parametri generici va nel nome del metodo o classe.

Non sei sicuro di ciò che la vostra situazione è ma potrebbe essere necessario fare uso di riflessione per chiamare quei metodi:

public class A 
{ 
    public void Do<T>() 
    { 
     if(typeof(T).IsValueType){ 
      // nasty reflection to call DoValueType 
     } 
     else { 
      // nasty reflection to call DoReferenceType 
     } 
    } 
    private void DoReferenceType<T>() where T : class { 

    } 
    private void DoValueType<T>() where T : struct { 

    } 
} 
Problemi correlati