2014-09-05 5 views
9

Ich versuche eine generische Methode in C# zu erstellen, die verschiedene Methoden auf der Basis des Argumentdatentyps in seinem Körper aufrufen und ihr Ergebnis anschließend verarbeiten wird. Ich versuche dies zu erreichen, indem ich eine generische Wrapper-Methode erstelle und dann mehrere Überladungen der Verarbeitungsmethode zur Verfügung stelle - einschließlich einer generischen, die verwendet wird, wenn keine spezifische Überladung verfügbar ist.C#: Generische Methode ruft keine spezifische Methodenüberladung auf

Wenn ich die Verarbeitungsmethode direkt aufrufen, wird die entsprechende Version korrekt ausgewählt. Wenn ich es jedoch von der Wrapper-Methode aus aufrufe, wählt es immer die generische, selbst wenn es eine passende Überladung für den spezifischen Datentyp gibt, den ich ihm übergeben habe.

Gibt es eine Möglichkeit, den Code so anzupassen, dass er sich so verhält, wie ich es brauche? Oder muss ich einen anderen Ansatz verwenden?

Ich brauche den Code mit Mono 2.6 kompatibel sein.

using System; 

class Program 
{ 
    static void Func<T>(T val) 
    { 
     Console.WriteLine("Generic Func"); 
    } 

    static void Func(int val) 
    { 
     Console.WriteLine("Int Func"); 
    } 

    static void Func(string val) 
    { 
     Console.WriteLine("String Func"); 
    } 

    static void FuncWrap<T>(T val) 
    { 
     Console.Write("Wrap: "); 
     Func(val); 
    } 

    static void Main(string[] args) 
    { 
     Func(2); 
     Func("Potato"); 
     Func(2.0); 

     FuncWrap(2); 
     FuncWrap("Potato"); 
     FuncWrap(2.0); 

     Console.Read(); 
    } 
} 
+0

können Sie FuncWrap-Überladungen verwenden, die ebenfalls ein int und eine Zeichenfolge verwenden (oder einfach die Func-Methoden direkt ohne Umbruch verwenden). –

Antwort

13

Gibt es eine Möglichkeit richtig dieses Verhalten?

Es ist bereits das richtige Verhalten gemäß der C# -Sprachspezifikation. Die Überladung von Func, die innerhalb FuncWrap aufgerufen wird, wird normalerweise zur Kompilierungszeit bestimmt, so kann es eine andere Func Überladung basierend auf dem Ausführungszeittyp nicht auswählen.

Eine Möglichkeit, das Verhalten zu ändern, ist jedoch dynamische Eingabe zu verwenden:

static void FuncWrap<T>(T val) 
{ 
    Console.Write("Wrap: "); 
    dynamic x = val; 
    Func(x); 
} 

, die jetzt der Überladungsauflösung zur Ausführungszeit auf der Grundlage des tatsächlichen Typen des Werts von x durchführen werden. Dies verursacht einen Leistungsaufwand, sollte aber tun, was Sie wollen.

Alternativ könnten Sie schwer Code Kenntnis der Überlastung:

static void FuncWrap<T>(T val) 
{ 
    Console.Write("Wrap: "); 
    if (typeof(T) == typeof(string)) 
    { 
     Func((string)(object)val); 
    } 
    else if (typeof(T) == typeof(int)) 
    { 
     Func((int)(object)val); 
    } 
    else 
    { 
     Func(val); 
    } 
} 

dass, obwohl klar ist ziemlich schrecklich.

+0

Sorry, ich habe es nicht richtig geschrieben. Ich meinte "richtig", wie es sich so verhält, wie ich es brauche. Die Dynamik scheint nicht mit Mono 2.6 zu arbeiten (ich verwende den Code in der Unity-Engine). Ja, die zweite Methode ist nicht wünschenswert, ich bin auf der Suche nach etwas sauberer (und idealerweise schneller). –

+0

@TomFrooxiusMariank: Wenn man sich die Versionshinweise für Mono 2.6 anschaut, sollte es * unterstützt werden - es kann sein, dass Unity tatsächlich Dinge auf ein älteres Profil beschränkt. (Es würde das .NET 4-Profil benötigen.) Ohne 'dynamic' wäre es wahrscheinlich am besten, wenn der Hack am Ende meiner Antwort steht ... das wird ziemlich gut funktionieren (besser als das dynamische, das im Grunde verwendet wird) Betrachtung). Du könntest dich natürlich selbst besinnen, aber das wird nicht schnell gehen. Wenn keines davon geeignet ist, sollten Sie ein Redesign in Betracht ziehen. –

+0

Ich sehe, ich bin wahrscheinlich kein Glück mit der aktuellen Unity-Version von Unity, dann werde ich überprüfen, ob ich das Profil irgendwie ändern kann, aber ich bin mir nicht sicher, ob das nicht irgendwelche unerwünschten Konsequenzen haben wird. Wenn es nicht funktioniert, werde ich wahrscheinlich den Code überarbeiten, um diese Funktion zu vermeiden. Danke für Ihre Hilfe. –

Verwandte Themen