2012-12-09 17 views
6

Ich möchte Methodenüberladung verwenden, um unterschiedliche Ergebnisse nach verschiedenen generischen Typen zu erhalten. Es funktioniert nicht. Mein Code zeigt es deutlich.C# Überladung Fehler für den generischen Typ

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 

Warum My<int> Anrufe Helper.Can (Object o) statt Helper.Can (int i)?

Antwort

4

Es funktioniert nicht so.

Überladungen werden zur Kompilierzeit vollständig aufgelöst. Generische Typparameter werden zur Laufzeit aufgelöst.
Da der Compiler nicht weiß, dass Tint ist, wird Ihr Code immer Can(Object) aufrufen.

+0

Great.Thank Sie – zilong

+0

Ich würde nicht ganz mit der Aussage übereinstimmen, dass "generische Typparameter zur Laufzeit aufgelöst werden". Wenn dies der Fall war, konnte der Compiler zur Kompilierzeit nicht feststellen, dass Sie kein Int-Item von einer 'List ' bekommen können. Was * zur Kompilierzeit als nicht aufgelöst gilt, sind Vorkommnisse des generischen Typparameters in der generischen Klasse. –

+0

@ O.R.Mapper: Ich meinte innerhalb der generischen Klasse. – SLaks

1

es ist ein wenig ausführlich, aber man kann das erreichen, was Sie mithilfe Reflexion wollen:

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(); 
} 

diese Weise

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

Natürlich mit einem wenig zusätzlichen Handwerk (und Verwendung generischer Typen), könnten Sie dieses Snippet für viele verschiedene Situationen ausgiebig wiederverwenden.

Eine zusätzliche Bemerkung: In diesem Beispiel habe ich direkten Typvergleich für Ihr spezifisches Beispiel verwendet. Beachten Sie, dass dies beim Umgang mit geerbten Typen nicht richtig funktioniert (und natürlich gibt es auch einige zusätzliche Unklarheiten :).

3

Im Allgemeinen wird es lösen bei der Kompilierung Objekt, aber man kann es erst zur Laufzeit warten, erzählt von dem dynamischen Schlüsselwort:

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

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

So wird dies für Arbeit, was Sie versuchen zu tun und die richtige Überladung wird aufgerufen. Wie bei allem, was zur Laufzeit gelöst wird, sind jedoch Leistungskosten damit verbunden. Wahrscheinlich nicht viel von einem, aber wenn Sie diese Methode häufig nennen, könnte das Auswirkungen haben.

Verwandte Themen