Привести объект в десятичную? (обнуляемый десятичный) - PullRequest
31 голосов
/ 09 февраля 2009

Если есть в установщике свойства:

decimal? temp = value as decimal?;

значение = "90"

Но после приведения, temp равен null ...

Как правильно сделать этот актерский состав?

Ответы [ 4 ]

66 голосов
/ 09 февраля 2009

Распаковка работает, только если тип идентичен! Вы не можете распаковать object, который не содержит целевого значения. Что вам нужно, это что-то вроде

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

Это выглядит, является ли значение анализируемым как decimal. Если да, то присвойте его result; еще присваивать null. Следующий код делает примерно то же самое и может быть проще для понимания людьми, не знакомыми с условным оператором ?::

decimal tmpvalue;
decimal? result = null;
if (decimal.TryParse((string)value, out tmpvalue))
    result = tmpvalue;
5 голосов
/ 09 февраля 2009

вы должны разобрать десятичную. Но если вы хотите, чтобы десятичное число было нулевым, если строка неверна, используйте TryParse:

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

Таким образом, вы будете избегать исключений при разборе плохо форматированных строк.

Почти все примитивные типы предоставляют методы Parse и TryParse для преобразования из строки.

Рекомендуется также передать культуру для аргумента поставщика в метод, чтобы избежать проблем с десятичным разделителем. Если вы читаете из другой системы, CultureInfo.InvariantCulture, вероятно, является подходящим вариантом (но это не значение по умолчанию).

bool TryParse(string s, NumberStyles style,
  IFormatProvider provider, out decimal result)
2 голосов
/ 28 июня 2011

Если вы не хотите анализировать строки, но хотите убедиться, что вы получаете null, decimal или обнуляемый decimal, то вы можете сделать что-то вроде этого:

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

Вы могли бы сделать так, чтобы он возвращал значение NULL в последней строке, если вы хотите избежать исключений, хотя это не будет отличать реальные значения NULL от неправильных приведений.

Обратите внимание, что вы должны использовать оператор "is", так как оператор "as" не работает с типами значений, а приведение без проверки может вызвать исключение InvalidCastException.

Вы также можете сделать это методом расширения:

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

И используйте это так:

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

Это поможет избежать предупреждений контракта кода о распаковке нулевых ссылок.

2 голосов
/ 09 февраля 2009

и если вы используете decimal? temp = (decimal?)value;

...