Полагаю, этот ответ будет просто потерян между всеми остальными, но в любом случае, вот так.
Я попал на этот вопрос через Google, потому что хотел проверить, было ли string
numeric
, чтобы я мог просто использовать double.Parse("123")
вместо TryParse()
метода.
Почему? Потому что раздражает необходимость объявлять переменную out
и проверять результат TryParse()
, прежде чем вы узнаете, был ли сбой анализа или нет. Я хочу использовать ternary operator
, чтобы проверить, является ли string
numerical
, а затем просто проанализировать его в первом троичном выражении или указать значение по умолчанию во втором троичном выражении.
Как это:
var doubleValue = IsNumeric(numberAsString) ? double.Parse(numberAsString) : 0;
Это намного чище, чем:
var doubleValue = 0;
if (double.TryParse(numberAsString, out doubleValue)) {
//whatever you want to do with doubleValue
}
Я сделал пару extension methods
для этих случаев:
Метод расширения один
public static bool IsParseableAs<TInput>(this string value) {
var type = typeof(TInput);
var tryParseMethod = type.GetMethod("TryParse", BindingFlags.Static | BindingFlags.Public, Type.DefaultBinder,
new[] { typeof(string), type.MakeByRefType() }, null);
if (tryParseMethod == null) return false;
var arguments = new[] { value, Activator.CreateInstance(type) };
return (bool) tryParseMethod.Invoke(null, arguments);
}
Пример:
"123".IsParseableAs<double>() ? double.Parse(sNumber) : 0;
Поскольку IsParseableAs()
пытается проанализировать строку как соответствующий тип вместо того, чтобы просто проверять, является ли строка "числовой", она должна быть довольно безопасной. И вы даже можете использовать его для нечисловых типов, которые имеют метод TryParse()
, например DateTime
.
Метод использует рефлексию, и в итоге вы вызываете метод TryParse()
дважды, что, конечно, не так эффективно, но не все должно быть полностью оптимизировано, иногда удобство просто важнее.
Этот метод также можно использовать для простого разбора списка числовых строк в список double
или некоторого другого типа со значением по умолчанию без необходимости перехвата каких-либо исключений:
var sNumbers = new[] {"10", "20", "30"};
var dValues = sNumbers.Select(s => s.IsParseableAs<double>() ? double.Parse(s) : 0);
Метод расширения два
public static TOutput ParseAs<TOutput>(this string value, TOutput defaultValue) {
var type = typeof(TOutput);
var tryParseMethod = type.GetMethod("TryParse", BindingFlags.Static | BindingFlags.Public, Type.DefaultBinder,
new[] { typeof(string), type.MakeByRefType() }, null);
if (tryParseMethod == null) return defaultValue;
var arguments = new object[] { value, null };
return ((bool) tryParseMethod.Invoke(null, arguments)) ? (TOutput) arguments[1] : defaultValue;
}
Этот метод расширения позволяет вам анализировать string
как любой type
, у которого есть метод TryParse()
, и также позволяет указать значение по умолчанию, которое будет возвращаться в случае сбоя преобразования.
Это лучше, чем использовать троичный оператор с методом расширения, описанным выше, поскольку он выполняет преобразование только один раз. Это все еще использует отражение, хотя ...
Примеры:
"123".ParseAs<int>(10);
"abc".ParseAs<int>(25);
"123,78".ParseAs<double>(10);
"abc".ParseAs<double>(107.4);
"2014-10-28".ParseAs<DateTime>(DateTime.MinValue);
"monday".ParseAs<DateTime>(DateTime.MinValue);
Выходы:
123
25
123,78
107,4
28.10.2014 00:00:00
01.01.0001 00:00:00