Разбор строки в нулевой числовой тип (1 или 2 лайнера) - программирование
Подтвердить что ты не робот

Разбор строки в нулевой числовой тип (1 или 2 лайнера)

Сценарий

Разберите строку в числовой тип с нулевым значением. Если анализ не увенчался успехом, результат должен быть нулевым; в противном случае результатом должно быть проанализированное значение.

Вопрос

Для этого я всегда использовал следующий простой, но довольно раздражающий метод:

string numericString = "...";

decimal? numericValue;
decimal temp;
if (decimal.TryParse(numericString, out temp))
{
    numericValue = temp;
}
else
{
    numericValue = null;
}

Я использую вышеуказанный метод, потому что следующее не компилируется:

decimal temp;
decimal? numericValue = decimal.TryParse(numericString, out temp) ? temp : null;

Кто-нибудь знает версию первого бита кода, который является коротким, аккуратным и читаемым как второй бит? Я знаю, что всегда мог написать метод расширения, который инкапсулирует первый бит кода, но мне интересно, есть ли способ сделать то, что я хочу, без метода расширения.

4b9b3361

Ответ 1

Один простой явный тип делает его компилируемым:

decimal temp;
// typecast either 'temp' or 'null'
decimal? numericValue =
  decimal.TryParse(numericString, out temp) ? temp : (decimal?)null;

Другой вариант - использовать оператор default для нужного типа с нулевым значением:

decimal temp;
// replace null with default
decimal? numericValue =
  decimal.TryParse(numericString, out temp) ? temp : default(decimal?);

Ответ 2

Я бы сделал что-то вроде этого:

public delegate bool TryParseDelegate<T>(string str, out T value);

public static T? TryParseOrNull<T>(TryParseDelegate<T> parse, string str) where T : struct
{
    T value;
    return parse(str, out value) ? value : (T?)null;
}

decimal? numericValue = TryParseOrNull<decimal>(decimal.TryParse, numericString);

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

public static T? TryParseAs<T>(this string str, TryParseDelegate<T> parse) where T : struct
{
    T value;
    return parse(str, out value) ? value : (T?)null;
}

decimal? numericValue = numericString.TryParseAs<decimal>(decimal.TryParse);

Ответ 3

Просто разложите его на метод расширения:

public static decimal? ParseDecimal(this string s)
{
    decimal d;
    if (decimal.TryParse(s, out d))
        return d;
    return null;
}

Затем вы можете использовать его следующим образом:

numericValue = numericString.TryParseDecimal();

Ответ 4

Как насчет:

decimal? numericValue = 
    decimal.TryParse(numericString, out temp) ? temp : null as decimal?;

Это делает numericValue null, если сбой выполняется, и он хорош и чист.

Ответ 5

Проблема заключается в том, что temp является десятичной и null... является нулевым. Поскольку они не одного типа, сравнение между ними не выполняется, и вы получаете ошибку.

Попробуйте либо:

decimal? numericValue = decimal.TryParse(numericString, out temp) ? (decimal?)temp : null;

или

decimal? numericValue = decimal.TryParse(numericString, out temp) ? (decimal?)temp : (decimal?)null;

Ответ 6

Я думаю, вы должны обернуть его в метод для лучшей читаемости:

private decimal? ParseOrDefault(string decimalAsString, decimal? defaultIfInvalidString=null)
{
    decimal result;
    if (decimal.TryParse(decimalAsString, out result))
        return result;
    return defaultIfInvalidString;
}

[Test]
public void ParseOrDefaultTest()
{
    decimal? actual = ParseOrDefault("12", null);
    Assert.AreEqual(12m,actual);

    actual = ParseOrDefault("Invalid string", null);
    Assert.AreEqual(null, actual);
}