Kennt irgendjemand einen schnellen Weg in VB, um von einem String zu einem generischen Typ T
zu einem Werttyp ( Of T as Structure
) zu wechseln, wenn ich weiß, dass T
immer ein Zahlentyp sein wird?
Das ist zu langsam für meinen Geschmack:
%Vor% Aber es scheint die einzige gesunde Methode zu sein, von einem String
- & gt; %Code%. Ich habe versucht, Reflector zu verwenden, um zu sehen, wie T
funktioniert, und während ich von der Zeichenfolge zu einem bestimmten Zahlentyp über eine gehackte Version dieses Codes konvertieren kann, habe ich keine Ahnung, wie ich diesen Typ wieder in% co_de staue %, so dass es zurückgegeben werden kann.
Ich füge hinzu, dass ein Teil der Geschwindigkeitsstrafe, die ich (in einer Zeitschleife) sehe, darin besteht, dass der Rückgabewert einem Convert.ChangeType
-Wert zugewiesen wird. Wenn ich meine Klasse für einen bestimmten Zahlentyp (d. H.% Co_de%) stark type, kann ich die Leistung erheblich steigern, aber dann müsste die Klasse für jeden von mir verwendeten numerischen Typ dupliziert werden.
Es wäre fast nett, wenn es einen Konverter zu / von T
gäbe, während man in einer generischen Methode / Klasse daran arbeitet. Vielleicht gibt es und ich bin mir seiner Existenz nicht bewusst?
Fazit :
Beim Testen der drei unten angegebenen Implementierungen und meines ursprünglichen DirectCast / ChangeType-Formulars funktioniert @ peenuts Ansatz, einen vorbereiteten Delegaten zum Abrufen der Nullable(Of T)
-Methode von einem Basistyp zu verwenden. Es wird jedoch keine Fehlerüberprüfung durchgeführt, daher müssen sich Implementierer daran erinnern, dies nur mit Werttypen zu verwenden, für die eine UInt16
-Methode verfügbar ist. Oder erweitern Sie die folgenden, um eine Fehlerüberprüfung durchzuführen.
Alle Läufe wurden auf einem 32-Bit-System ausgeführt, auf dem Windows Server 2003 R2 mit 4 GB RAM ausgeführt wurde. Jeder "run" ist 1.000.000 Ausführungen (ops) der zu testenden Methode, die mit StopWatch zeitlich festgelegt und in Millisekunden zurückgemeldet wird.
Original T
:
Verwenden von Parse
und Aufruf von Parse
, um die Methode DirectCast(Convert.ChangeType(myStr, GetType(T)), T)
zu erhalten:
Konrads Ansatz zum Generieren von IL-Code für den Zugriff auf die System.Reflection
-Methode und Speichern des Aufrufs in einem Delegaten:
peenuts Ansatz, einen Delegaten zu verwenden, um direkt auf die Methode InvokeMethod
zuzugreifen:
Im Vergleich dazu ist Peenuts Ansatz bei einer 1.000.000-fachen Ausführung in einer engen Schleife fast 200 ms schneller, so dass sein Ansatz gewinnt. Konrads war zwar nicht weit entfernt und ist selbst eine faszinierende Studie von Dingen wie ILGenerator. Stützen Sie auf alle, die beigetragen haben!
Ja, ich kenne eine schnellere Lösung: -)
Schnellere Lösung besteht darin, den vorbereiteten Delegaten für einen gegebenen (generischen) Typ T zu verwenden. Wenn Sie nur an String- & gt; (integrierter numerischer Typ) interessiert sind, können Sie die Parse-Methode einfach mit einem Argument (String) / p>
Programm zum Testen der Geschwindigkeit der Möglichkeiten. Beachten Sie, dass nur die ersten beiden Methoden generisch sind, die 3. und 4. Methode nur zum Vergleich.
%Vor%Sie können die Anzahl der getesteten Elemente ändern, wenn Sie möchten. Ich habe 12345678 zufällige Ganzzahlen verwendet. Programmausgaben für mich:
%Vor%Verhältnis der Zeiten: 3.5176071 / 2.9348792 = 1.20
Hier ist ein anderer Ansatz, der die zuvor erwähnte DynamicMethod
verwendet.
Wieder konnte ich den VB-Code nicht testen (der Mono-Compiler erstickt beim Testanruf, aber nicht am Code selbst), aber ich glaube, dass er korrekt ist. Sein C # -Aquivalent funktioniert und der folgende Code ist eine 1: 1-Übersetzung:
%Vor% Dieser Code kann gelöscht werden, wenn Sie eine aktuelle Version von VB haben. Auch hier kennt der Mono-Compiler noch nicht Option Infer
und ähnliches.
Was dieser Code tut, ist eine separate Analysemethode für jeden aufgerufenen Code zu kompilieren. Diese Analysemethode delegiert das tatsächliche Parsing nur an die freigegebene T.Parse
-Methode des Typs (z. B. Integer.Parse
). Einmal kompiliert, erfordert dieser Code kein zusätzliches Casting, kein Boxing und keine Nullable
s.
Der Code wird wie folgt aufgerufen:
%Vor%Abgesehen von dem einmaligen Aufwand für die Kompilierung sollte diese Methode so schnell wie möglich sein, da kein zusätzlicher Aufwand anfällt: nur ein Funktionsaufruf an die eigentliche Parsing-Routine. Es wird nicht schneller als das.
Wahrscheinlich keine Antwort, stattdessen eine andere Frage. Was erreichen Sie mit dieser Methode? Stellen wir uns vor, Sie haben eine solche Methode implementiert (Sorry für C # in Vb.Net Post, aber hoffentlich bekommen Sie die Idee):
%Vor%und Sie werden diese Methode nur für einen begrenzten Bereich von Typen verwenden: double, int, Int16 usw. Sie werden es also so verwenden:
%Vor%Ich sehe keinen Nutzen in einer solchen Methode, weil aus dem gleichen Grund ohne diese Methode würden Sie schreiben:
%Vor%Ich möchte also sagen, dass Sie ohne Ihre magische Methode dieselbe Menge Code schreiben werden, um sie zu benutzen. Ich sehe keinen Nutzen dieser Methode. Fehle ich einen Anwendungsfall?
Ich habe keinen VB-Compiler, deshalb kann ich es nicht testen, aber das Folgende funktioniert in C #. Ich bezweifle, dass es aber schneller ist, da es Reflexion verwendet:
%Vor% Eine Möglichkeit, dies zu beschleunigen, besteht darin, eine dynamische Methode aus dem T.Parse
-Member anstelle von InvokeMember
zu erstellen und diese dynamische Methode für jeden Typ zwischenzuspeichern. Dies würde einen größeren Aufwand für den ersten Aufruf bedeuten (Kompilieren einer dynamischen Methode), aber nachfolgende Läufe wären schneller.
Tags und Links vb.net