Разбор строки в нулевой числовой тип (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;
Кто-нибудь знает версию первого бита кода, который является коротким, аккуратным и читаемым как второй бит? Я знаю, что всегда мог написать метод расширения, который инкапсулирует первый бит кода, но мне интересно, есть ли способ сделать то, что я хочу, без метода расширения.
Ответы
Ответ 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);
}