2009-02-09 7 views

Odpowiedz

64

Unboxing działa tylko wtedy, gdy typ jest identyczny! Nie można rozpakować pliku object, który nie zawiera wartości docelowej. Co potrzebne jest coś wzdłuż linii

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

Wygląda to, czy wartość jest parsable jako decimal. Jeśli tak, to przypisz ją do result; jeszcze przypisz null. Poniższy kod jest w przybliżeniu taka sama i może być łatwiejsze do zrozumienia dla osób nie zaznajomionych z operatorem warunkowym ?::

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

Nie użyłbym tutaj słowa "identyczne".Na przykład, możesz rozpakować między typami wyliczeń i ich typem podstawowym, T i T? Oraz niektórymi innymi przypadkami IIRC. CLR jest bardziej liberalny, niż można się było spodziewać. –

+0

(Ale tak, nie powinieneś oczekiwać, że unboxing przetworzy ciąg znaków :) –

+0

@Jon: czy masz lepsze sformułowanie? Jeśli tego nie zrobię, skopiuję twój komentarz do mojej odpowiedzi, ponieważ dobrze to wyraża. –

2

a jeśli używasz decimal? temp = (decimal?)value;

+0

to nie działa. Nie potrafię wyjaśnić dlaczego. W trybie debugowania Visual Studio chce pokazać demontaż ... – Natrium

+1

To bardzo dziwne, ponieważ działa dobrze na mojej stronie ..... – StevenMcD

+0

Nie będzie działać, jeśli wartość zawiera instancję ciągu. Powinien działać, jeśli posiada przykład dziesiętny. – pauloya

5

należy przeanalizować po przecinku. Ale jeśli chcesz, aby Twój dziesiętny być zerowy, gdy ciąg nie jest prawidłowy, należy TryParse:

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

W ten sposób można uniknąć wyjątki podczas parsowania źle sformatowane ciągi.

Prawie wszystkie typy pierwotne udostępniają metody Parse i TryParse do konwertowania z ciągu znaków.

Zaleca się również przekazanie kultury dla argumentu dostawcy metody, aby uniknąć problemów z separatorem dziesiętnym. Jeśli czytasz z innego systemu, prawdopodobnie jest to metoda CultureInfo.InvariantCulture (ale nie jest to ustawienie domyślne).

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

Zapomniałem (dziesiętnego?) Rzutu za zerową ... przepraszam, ale część kultury jest nadal ważna. – thinkbeforecoding

+3

Ta odpowiedź jest niepoprawna, ponieważ przypisanie "wartości" do "temp" nie będzie działać. Powinno być ? parsedValue: (dziesiętna?) null; – offner

1

Jeśli nie chcesz zanalizować ciągi, ale mieć pewność, że otrzymasz albo null, A decimal lub pustych decimal, to mógłby zrobić coś takiego:

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(); 
} 

Mogłabyś spraw, aby zamiast tego zwracał wartość null w ostatnim wierszu, jeśli chcesz uniknąć wyjątków, chociaż nie rozróżniłoby to rzeczywistych wartości null od złych rzutowań.

Należy zauważyć, że należy użyć operatora "jest", ponieważ operator "as" nie działa w przypadku typów wartości, a rzutowanie bez sprawdzania może wywołać wyjątek InvalidCastException.

Można również zrobić to metodę rozszerzenia:

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(); 
    } 
} 

i używać go tak:

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

Pomoże to uniknąć ostrzeżenia umowy o kod unboxing referencji null.

+0

Czy przetestowałeś swoją metodę rozszerzenia? Próbowałem go i otrzymałem wyjątek NullReferenceException dla prawidłowej podwójnej wartości, która musiała zostać przekonwertowana na liczbę dziesiętną z wartością zerową. – Shiva

+0

@Shiva Metoda rozszerzenia nie jest przeznaczona dla podwójnych, ponieważ stwierdza ona w pierwszym wierszu: "otrzymujesz wartość null, dziesiętną lub liczby dziesiętne z wartościami zerowymi " –

Powiązane problemy