我想这个答案会在所有其他答案之间丢失,但无论如何,这里是。
我最终通过 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 解析为具有 TryParse() 方法的任何 type,它还允许您指定在转换失败时返回的默认值。
这比在上面的扩展方法中使用三元运算符要好,因为它只进行一次转换。它仍然使用反射...
示例:
"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