2009-04-28 16 views
0

Ich habe eine überladene Hilfsmethode namens CheckDuration mit folgenden Funktionssignaturen.Können Sie eine Deklaration generischer Typen mit variabler Länge deklarieren?

private static Action<int> CheckDuration(Action action) 
    private static Action<int> CheckDuration<T>(Action<T> action, T arg) 

Grundsätzlich CheckDuration druckt auf Konsole, wie lange es ein Verfahren zu laufen hat.

Jetzt möchte ich die Dauer einer Methode überprüfen, die 2 Argument dauert.
Also würde ich eine andere überladene CheckDuration mit folgender Methodensignatur erstellen müssen.

private static Action<int> CheckDuration<T, U>(
     Action<T, U> action, T arg1, U arg2) 

Gibt es eine Möglichkeit, dies mehr anmutig zu handhaben?
Ich dachte an so etwas wie

private static Action<int> CheckDuration<params T>(
     Action<params T> action, params T arg) 

, das funktioniert natürlich nicht.

[UPDATE] Ich werde diese Frage für jetzt offen lassen, um zu sehen, ob jemand für diese Art von Problem eine Lösung gefunden hat.

Antwort

5

Leider ist das, was Sie bereits haben, ungefähr so ​​sauber wie es geht. C# unterstützt nicht die Verwendung von params für generische Typparameter und die Unterstützung so etwas wäre sehr schwierig. Ihre ursprüngliche Lösung ist gut und entspricht den Delegierten in der BCL, wie die Action Delegierten, die Definitionen überladen haben, um unterschiedliche Anzahl von Argumenten zu übernehmen.

+0

Aus Neugier, können Sie mir bitte sagen, warum es sehr schwierig wäre? Ich bin nur neugierig :) –

0

Nein, es gibt keinen Weg. Ich nehme jedoch an, dass für diese "CheckDuration" sowohl T als auch U entweder eine gut definierte Schnittstelle implementieren oder von einer Basisklasse erben sollten (oder andernfalls werden Sie viel Reflexion durchführen, was den Verwendungszweck irgendwie zunichtemacht Generika). So betrachten:

Action<int> CheckDuration<T>(Action<T> action, params T[] args) 
    where T : ISupportCheckDuration 

Und Sie werden in der Lage sein, etwas zu stopfen, die da drin ISupportCheckDuration -kompatibel ist.

+0

Leider sind Sie mit diesem Beispiel gezwungen, einen Typ zu haben, da alle Argumente vom Typ T sind. –

+0

Nein, sie sollten alle ISupportCheckForDuration oder was auch immer implementieren. Diese können absolut unterschiedliche Typen sein, solange sie diese Bedingung erfüllen. –

+0

Anton Goglev: Ich habe darüber nachgedacht, "Console.WriteLine" zu übergeben, aber da es "params object []" erwartet, konnte ich es nicht für diesen Fall verwenden. – Sung

0

Werfen Sie einen Blick auf Postsharp:

http://www.postsharp.org/

Ich denke, es könnte Ihnen helfen. Sehen Sie sich das Beispiel für die Ablaufverfolgung an. Ich denke, du könntest es anpassen, um dein Timing durchzuführen. Dann können Sie jeder Methode unabhängig von der Anzahl der benötigten Argumente einfach ein Attribut hinzufügen.

Chris

3

Sie können es nicht ganz tun, wie Sie wollen, aber Sie können das gleiche Ziel erreichen:

public static class MethodTimer 
{ 
    public static long Run(Action action) 
    { 
     var sw = System.Diagnostics.Stopwatch.StartNew(); 
     action(); 
     sw.Stop(); 
     return sw.ElapsedMilliseconds; 
    } 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     long time = MethodTimer.Run(() => File.Open(@"c:\test.txt", 
      FileMode.CreateNew)); 
     Console.WriteLine(time); 
     Console.ReadLine(); 
    } 
} 

könnten Sie auch diese als eine Erweiterung Methode definieren, damit Ihr Code sein könnte:

 Action act =() => File.Open(@"c:\test.txt", FileMode.CreateNew); 
     time=act.Time(); 

diese Methode als würde definiert:

public static class MethodTimer 
    { 
     public static long Time(this Action action) 
     { 
      var sw = System.Diagnostics.Stopwatch.StartNew(); 
      action(); 
      sw.Stop(); 
      return sw.ElapsedMilliseconds; 
     } 
    } 

bearbeiten

Sie müssen keine dieser Ansatz keine neuen Methoden definieren, wird ein Verschluss um die Methode, die Sie zu Zeit möchten. Also:

MethodTimer.Time(()=> File.Open("",FileMode.Open); 
MethodTimer.Time(()=> myObject.TestMethod(123,1231,"another param")); 

Und so weiter und so weiter.

+0

Es scheint, als ob sogar mit Ihrem Ansatz der Erweiterungsmethode eine neue Methode für jede Action-Deklaration erstellt werden müsste ... – Sung

+2

Nein, Sie brauchen nur die für Action. Die Closure bindet die Methodenargumente, so dass die Aktion sie nie an die Methode übergeben muss. – munificent

0

Nicht möglich mit Generics, aber mit C +/CLI Variadic Vorlagen (wenn es Unterstützung für sie erhält), können Sie es tun.

+0

Ich bin nicht vertraut mit C++ - Vorlagen, aber wenn das Schlimmste schlimmer wird, würde ich es überprüfen. – Sung

Verwandte Themen