Generics und NULL-Typ

8

Angenommen, ich habe eine Methode, die int als String akzeptiert und den int zurückgibt, wenn die Syntaxanalyse erfolgreich ist, oder andernfalls einen Nullwert.

%Vor%

Wie kann diese Methode so umgeschrieben werden, dass sie nicht nur mit int ?, sondern auch lang ?, dezimal? und DateTime? ?

    
Phillip Ngan 10.12.2009, 04:55
quelle

7 Antworten

14

Es ist lustig, dass du es erwähnen solltest, weil ich neulich gerade mit etwas herumgespielt habe:

%Vor%

Es ist ein ähnlicher Ansatz, aber denken Sie daran wie eine bessere TryParse -Methode, die Tuple<Boolean, T?> zurückgibt (dies erfordert .NET 4). Die erste Eigenschaft des Tupels ist ein boolescher Wert, der angibt, ob der Parsingversuch erfolgreich oder fehlgeschlagen ist, und die zweite Eigenschaft ist ein nullwertfähiger Wert für das Argument vom Typ generic, der null ist, wenn das Parsen fehlschlägt und der Wert beim Parsen erfolgreich ist.

Es funktioniert mit Reflektion, um eine statische Parse(String) -Methode aus dem generischen Typargument abzurufen und ruft diese Methode für die übergebene Zeichenfolge auf. Ich habe es als eine Erweiterungsmethode erstellt, um Ihnen zu erlauben, solche Dinge zu tun:

%Vor%

Leider funktioniert dies nicht in enums , da sie nicht die gleiche Signatur für die Parse-Methode haben. Sie könnten diese Erweiterung nicht benutzen, um enum zu analysieren, aber es wäre nicht schwer, dies zu hacken um einen speziellen Fall für Enums zu machen.

Eines der schönen Dinge bei diesem Ansatz ist, dass die Kosten für das Abrufen der Methode Parse über Reflektion nur bei der ersten Verwendung anfallen, da für alle folgenden Verwendungen ein statischer Delegat erstellt wird.

Noch eine Sache - das Einzige, was bei diesem Ansatz klobig ist, ist, dass es keine Spracherweiterungen oder syntaktischen Zucker gibt, mit denen es einfach wäre, damit zu arbeiten. Was ich mit diesem Code erreichen wollte, war ein less klobiger Weg zur Verwendung der Standardmethoden TryParse , die in der BCL existieren.

Ich persönlich finde dieses Muster eher hässlich:

%Vor%

hauptsächlich, weil es im Voraus eine Variablendeklaration und die Verwendung eines Parameters out erfordert. Mein Ansatz oben ist nicht wirklich viel besser:

%Vor%

Was wirklich cool wäre, wäre eine C # -Sprachenerweiterung zu sehen, die mit einem Tuple<Boolean, T?> funktioniert, damit wir mit diesem Typ reibungslos arbeiten können, aber ich habe das Gefühl, je mehr ich darüber schreibe, dass es nicht funktioniert Das scheint wirklich machbar.

    
Andrew Hare 10.12.2009, 04:58
quelle
3

Anstelle des Fragezeichens können Sie explizit das Schlüsselwort Nullable verwenden: zum Beispiel

int? entspricht Nullable<int>

Daher sollte der Wechsel des ursprünglichen Designs zu Nullable<T> ParseValue(string valueAsString ) der Trick sein: Mach einfach die generische Implementierung danach.

    
Dr. Xray 10.12.2009 05:10
quelle
3

Am besten implementieren Sie eine Erweiterungsmethode, und Sie können Enumerationen sogar analysieren. Auf diese Weise erhalten Sie eine Nullable & lt; ForAnyValueType & gt; so:

%Vor%     
Arturo Martinez 08.03.2011 16:38
quelle
2

Wenn Sie auf C # 4.0 warten können, können Sie das Schlüsselwort dynamic verwenden, das ein solches Szenario löst.

    
Ron Klein 10.12.2009 05:15
quelle
1

Ich sehe nicht wirklich, warum wir das Tuple in Andrews Lösung verwenden, solange wir sowieso eine Nullable zurückgeben, scheint es, als würde man das Gleiche zweimal machen. Ich änderte seine Lösung, um TryParse zu verwenden und erlaubte, entweder einen Nullable oder einen bestimmten Standardwert als Argument anzugeben.

%Vor%     
mizuki nakeshu 24.08.2012 10:13
quelle
0

Tatsächlich können Sie aktualisieren, was Matts Code getan hat und es machen, und hier ist der Code:

%Vor%

Und Sie können es auch so verwenden: doppelt? i = TryParse ("111.111"); int? a = TryParse ("111");

    
jujusharp 10.12.2009 07:56
quelle
0

Diese Typen, die Sie aufgelistet haben, haben alle eine statische Methode namens TryParse. Sie sehen ähnlich aus, aber tatsächlich sind die Signaturen völlig unterschiedlich. Sie folgen einem ähnlichen 'Muster', aber das ist vom Compiler nicht erkennbar.

Sie könnten versuchen, etwas wie folgt zu tun:

%Vor%

Allerdings können Sie nicht. Der Compiler hat keine Möglichkeit (zur Kompilierzeit) zu wissen, wie man den Typ 'T' in einen Int (oder einen anderen Typ) umwandelt.

Sie können das Double-Cast-Verfahren durchführen. (Danke, Dotson)

Verwendung:

%Vor%     
Matt Brunell 10.12.2009 05:42
quelle

Tags und Links