有没有尝试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);
}

但不能取消IConvertibleToInt32方法。因此,如果无法转换值,则无法避免出现异常。

第二:有没有办法检查对象是否包含隐式运算符?

这非常糟糕:

if (value.GetType().GetMethods().FirstOrDefault(method => method.Name == "op_Implicit" && method.ReturnType == typeof(int)) != null)
{
    result = (int)value;
    return true;
}

有没有尝试Convert.ToInt32.避免异常

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
}