有没有尝试Convert.ToInt32.避免异常
本文关键字:异常 ToInt32 Convert 有没有 | 更新日期: 2023-09-27 18:27:40
我想知道是否有一种"安全"的方法可以将对象转换为int
,避免出现异常。
我在找类似public static bool TryToInt32(object value, out int result);
的东西
我知道我可以做这样的东西:
public static bool TryToInt32(object value, out int result)
{
try
{
result = Convert.ToInt32(value);
return true;
}
catch
{
result = 0;
return false;
}
}
但我宁愿避免出现例外情况,因为它们会减缓这个过程。
我认为这更优雅,但它仍然"便宜":
public static bool TryToInt32(object value, out int result)
{
if (value == null)
{
result = 0;
return false;
}
return int.TryParse(value.ToString(), out result);
}
有人有更好的主意吗?
更新:
这听起来有点像分叉,但将对象转换为字符串会迫使实现者创建一个清晰的ToString()
函数。例如:
public class Percentage
{
public int Value { get; set; }
public override string ToString()
{
return string.Format("{0}%", Value);
}
}
Percentage p = new Percentage();
p.Value = 50;
int v;
if (int.TryParse(p.ToString(), out v))
{
}
这出了问题,我可以在这里做两件事,或者像这样实现IConvertable
:
public static bool ToInt32(object value, out int result)
{
if (value == null)
{
result = 0;
return false;
}
if (value is IConvertible)
{
result = ((IConvertible)value).ToInt32(Thread.CurrentThread.CurrentCulture);
return true;
}
return int.TryParse(value.ToString(), out result);
}
但不能取消IConvertible
的ToInt32
方法。因此,如果无法转换值,则无法避免出现异常。
第二:有没有办法检查对象是否包含隐式运算符?
这非常糟糕:
if (value.GetType().GetMethods().FirstOrDefault(method => method.Name == "op_Implicit" && method.ReturnType == typeof(int)) != null)
{
result = (int)value;
return true;
}
int variable = 0;
int.TryParse(stringValue, out variable);
如果无法解析,则变量将为0。看见http://msdn.microsoft.com/en-us/library/f02979c7.aspx
从注释中引出。响应为否。如果不抛出异常,就无法执行Convert.ToInt32(object)
所做的操作。你可以做一些类似的事情(而且你已经做了)。我唯一要优化的是value
已经是int
的情况。
if (value is int)
return (int)value;
您不能做为Convert.ToInt32(object)
,因为Convert.ToInt32(object)
不会简单地测试value
是否为short, int, long, ushort, ...
,然后对其进行强制转换。它检查value
是否为IConvertible
。如果是,则使用IConvertible.ToInt32
。遗憾的是,接口IConvertible
相当糟糕:它没有非抛出方法(IConvertible.Try*
)
虽然很愚蠢(但可能不太多),但有人可以制作一个UnixDateTime
结构:(UnixTime是从1970-01-01午夜开始的秒数),其中IConvertible.ToInt32
返回这个秒数,而ToString()
返回一个格式化的日期。所有的int.TryParse(value.ToString(), out parsed)
都会窒息,而Convert.ToInt32
会完美地工作。
这个使用类型转换器的版本只会在万不得已的情况下转换为字符串,但不会引发异常:
public static bool TryToInt32(object value, out int result)
{
if (value == null)
{
result = 0;
return false;
}
var typeConverter = System.ComponentModel.TypeDescriptor.GetConverter(value);
if (typeConverter != null && typeConverter.CanConvertTo(typeof(int)))
{
var convertTo = typeConverter.ConvertTo(value, typeof(int));
if (convertTo != null)
{
result = (int)convertTo;
return true;
}
}
return int.TryParse(value.ToString(), out result);
}
这里不需要重新发明轮子。使用int.TryParse来实现您的目标。它返回一个bool来显示是否解析了值。并且如果被解析,则结果被保存在输出变量中。
int result;
object a = 5;
if(int.TryParse(a.ToString(),out result))
{
Console.WriteLine("value is parsed"); //will print 5
}
object b = a5;
if(int.TryParse(b.ToString(),out result))
{
Console.WriteLine("value is parsed");
}
else
{
Console.WriteLine("input is not a valid integer"); //will print this
}
返回一个可以为null的int。这样就可以知道是否解析了0。
int? value = int.TryParse(stringValue, out int outValue)
? outValue
: default(int?);
我将使用您已经在做的事情的混合;
- 检查对象是否为null-返回false和值0
- 尝试直接转换-如果成功,则返回true和转换后的值
- 尝试分析值。ToString()-如果成功,则返回true和解析的值
- 任何其他情况-返回false和值0,因为对象不可转换/可解析
生成的代码:
public static bool TryToInt32(object value, out int result)
{
result = 0;
if (value == null)
{
return false;
}
//Try to convert directly
try
{
result = Convert.ToInt32(value);
return true;
}
catch
{
//Could not convert, moving on
}
//Try to parse string-representation
if (Int32.TryParse(value.ToString(), out result))
{
return true;
}
//If parsing also failed, object cannot be converted or paresed
return false;
}
我写了这个烂摊子,看着它让我很难过。
using System;
using System.Globalization;
internal static class ObjectExt
{
internal static bool TryConvertToDouble(object value, out double result)
{
if (value == null || value is bool)
{
result = 0;
return false;
}
if (value is double)
{
result = (double)value;
return true;
}
var text = value as string;
if (text != null)
{
return double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out result);
}
var convertible = value as IConvertible;
if (convertible == null)
{
result = 0;
return false;
}
try
{
result = convertible.ToDouble(CultureInfo.InvariantCulture);
return true;
}
catch (Exception)
{
result = 0;
return false;
}
}
}
编辑请注意,当问题是int时,我回答了double,保持不变。也许对某人有用。
我喜欢这样做:
object v = someValue;
if (int.TryParse($"{v}", out var extractedValue))
{
// do something with extractedValue
}