2009-02-09 9 views

Antwort

64

Unboxing funktioniert nur, wenn der Typ identisch ist! Sie können ein object nicht auspacken, das den Zielwert nicht enthält. Was Sie brauchen, ist etwas entlang der Linien von

decimal tmpvalue; 
decimal? result = decimal.TryParse((string)value, out tmpvalue) ? 
        tmpvalue : (decimal?)null; 

Das sieht, ob der Wert als decimal parsable ist. Wenn ja, dann weisen Sie es result zu; sonst zuweisen null. Der folgende Code funktioniert in etwa gleich und könnte einfacher sein, für Menschen, die nicht vertraut mit dem bedingten Operator zu verstehen ?::

decimal tmpvalue; 
decimal? result = null; 
if (decimal.TryParse((string)value, out tmpvalue)) 
    result = tmpvalue; 
+2

Ich würde hier nicht das Wort "identisch" verwenden.Zum Beispiel können Sie die Enum-Typen und ihren zugrunde liegenden Typ, T und T?, Und einige andere ungerade Fälle IIRC aufheben. Die CLR ist toleranter, als man erwarten könnte. –

+0

(Aber ja, du solltest nicht erwarten, dass das Unboxing eine Zeichenkette analysiert :) –

+0

@Jon: hast du eine bessere Formulierung? Da ich dies vermisse, werde ich deinen Kommentar in meine Antwort kopieren, weil er den Vorbehalt schön ausdrückt. –

2

und wenn Sie decimal? temp = (decimal?)value;

+0

das funktioniert nicht. Ich kann nicht erklären warum. Im Debug-Modus möchte Visual Studio die Disassembly zeigen ... – Natrium

+1

Das ist sehr seltsam, weil es auf meiner Seite funktioniert ..... – StevenMcD

+0

Es wird nicht funktionieren, wenn Wert eine Instanz von String enthält. Es sollte funktionieren, wenn es eine Instanz von dezimal enthält. – pauloya

5

verwenden, sollten Sie das Dezimalsystem analysieren. Aber wenn Sie Ihre dezimal wollen null sein, wenn die Zeichenfolge nicht korrekt ist, verwenden TryParse:

decimal parsedValue; 
decimal? temp = decimal.TryParse(value, out parsedValue) 
       ? value 
       : (decimal?)null; 

diese Weise werden Sie Ausnahmen vermeiden, während krank formated Strings parsen.

Fast alle primitiven Typen bieten eine Parse- und eine TryParse-Methode zum Konvertieren aus einer Zeichenfolge.

Es wird auch empfohlen, eine Kultur für das Provider-Argument an die Methode zu übergeben, um Probleme mit dem Dezimaltrennzeichen zu vermeiden. Wenn Sie von einem anderen System lesen, ist CultureInfo.InvariantCulture wahrscheinlich der Weg (aber es ist nicht der Standard).

bool TryParse(string s, NumberStyles style, 
    IFormatProvider provider, out decimal result) 
+0

Ich hatte die (Dezimal?) Cast für Null vergessen ... sorry, aber der Kulturteil ist immer noch wichtig. – thinkbeforecoding

+3

Diese Antwort ist falsch, da die Zuweisung von 'Wert' zu 'Temp' nicht funktioniert. Es sollte sein ? parsedValue: (dezimal?) null; – offner

1

Wenn Sie keine Strings analysieren wollen, aber wollen sicherstellen, dass Sie entweder null erhalten, ein decimal oder ein Nullable-decimal, dann könnte man so etwas tun:

public static Nullable<T> Convert<T>(object input) 
    where T : struct 
{ 
    if (input == null) 
     return null; 
    if (input is Nullable<T> || input is T) 
     return (Nullable<T>)input; 
    throw new InvalidCastException(); 
} 

Sie könnten Lassen Sie es in der letzten Zeile null zurückgeben, wenn Sie Ausnahmen vermeiden möchten, obwohl dies nicht zwischen echten Nullwerten und schlechten Umwandlungen unterscheiden würde.

Beachten Sie, dass Sie den Operator "is" verwenden müssen, da der Operator "as" bei Werttypen nicht funktioniert und das Umwandeln ohne Überprüfung eine InvalidCastException auslösen kann.

Sie könnten auch sie eine Verlängerung Methode machen:

public static class ObjectExtensions 
{ 
    public static Nullable<T> ToNullable<T>(this object input) 
     where T : struct 
    { 
     if (input == null) 
      return null; 
     if (input is Nullable<T> || input is T) 
      return (Nullable<T>)input; 
     throw new InvalidCastException(); 
    } 
} 

Und es wie folgt verwenden:

object value = 123.45m; 
decimal? dec = value.ToNullable<decimal>(); 

Dies wird helfen, Code Vertrag Warnungen über Unboxing null Referenzen zu vermeiden.

+0

Haben Sie Ihre Erweiterungsmethode getestet? Ich habe es ausprobiert und eine NullReferenceException für einen gültigen doppelten Wert erhalten, der in Nullwerte umgewandelt werden musste – Shiva

+0

@Shiva Die Erweiterungsmethode ist nicht für Doubles gedacht, da sie in der ersten Zeile besagt: "dass Sie entweder null, eine Dezimalzahl oder eine nullwertfähige Dezimalzahl " –

Verwandte Themen