2012-12-09 14 views
6

Desidero utilizzare il metodo overload per ottenere risultati diversi in base a diversi tipi generici. Non funziona. Il mio codice lo mostra chiaramente.errore di sovraccarico C# per tipo generico

static class Helper 
{ 

    public static bool Can(int i) 
    { 
     return true; 
    } 

    public static bool Can(Object o) 
    { 
     return false; 
    } 
} 

class My<T> 
{ 
    public static bool can = Helper.Can(default(T)); 
} 

Console.WriteLine(Helper.Can(default(int)));//True,it is OK 

Console.WriteLine(My<int>.can);//false?? why the overload doesn't work 
Console.WriteLine(My<Object>.can);//false 

Perché My<int> chiamate Helper.Can (Object o) piuttosto che Helper.Can (int i)?

risposta

4

Non funziona in questo modo.

I sovraccarichi vengono risolti interamente in fase di compilazione; i parametri di tipo generico vengono risolti in fase di esecuzione.
Dal momento che il compilatore non sa che è , il tuo codice chiamerà sempre Can(Object).

+0

Great.Thank you – zilong

+0

Non sono d'accordo con l'affermazione che "i parametri di tipo generico vengono risolti in fase di esecuzione". Se così fosse, il compilatore non potrebbe dire al momento della compilazione che non è possibile ottenere un elemento int da un 'Elenco '. Quello che * è * considerato irrisolto in fase di compilazione sono occorrenze del parametro di tipo generico all'interno della classe generica. –

+0

@ O.R.Mapper: intendevo all'interno della classe generica. – SLaks

1

è un po 'prolisso, ma si potrebbe ottenere quello che vuoi utilizzando Riflessione:

class My<T> 
{ 
    static bool doStuff() 
    { 
     var rightMehod = typeof(Helper).GetMethods().Where(p => 
      { 
       if (!p.Name.Equals("Can")) 
        return false; 

       if (!p.ReturnType.Equals(typeof(bool))) 
        return false; 

       if (p.GetParameters().Length != 1) 
        return false; 

       var par = p.GetParameters().First(); 
       return par.ParameterType.Equals(typeof(T)); 
      }).FirstOrDefault(); 

     if (rightMehod == null) 
     { 
      return Helper.Can(default(T)); 
     } 
     else 
     { 
      return (bool)rightMehod.Invoke(null, new object[] { default(T) }); 
     } 
    } 

    public static bool can = doStuff(); 
} 

In questo modo,

My<string>.can == false 
My<int>.can == true 
My<object>.can == false 

Naturalmente, con un po' di mestiere in più (e utilizzo di tipi generici), si sarebbe in grado di riutilizzare questo snippet estensivamente per molte situazioni diverse.

Un'osservazione aggiuntiva: in questo esempio, ho utilizzato il confronto diretto dei tipi per l'esempio specifico. Nota che questo non funzionerà correttamente quando si ha a che fare con tipi ereditati (e, naturalmente, ci sono anche altre ambiguità :).

3

In generale, si risolverà ad oggetto al momento della compilazione, ma si può dire che aspettare fino al runtime utilizzando la parola chiave dinamica:

class My<T> 
{ 
    public static bool can = CanWithDynamic(); 

    private static bool CanWithDynamic() { 
     dynamic runtimeT = default(T); 
     return Helper.Can(runtimeT); 
} 

Quindi, questo lavoro per quello che stai cercando da fare e verrà chiamato il sovraccarico giusto. Tuttavia, come per tutto ciò che viene risolto in fase di esecuzione, è associato a un costo delle prestazioni. Probabilmente non granché, ma se chiami spesso questo metodo potrebbe avere un impatto.

Problemi correlati