55

我想知道是否有一种“安全”的方法可以将对象转换为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);
}

但是无法取消的ToInt32方法。IConvertible因此,如果无法转换值,则无法避免异常。

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

这很可怜:

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

7 回答 7

57
int variable = 0;
int.TryParse(stringValue, out variable);

如果无法解析,则变量为 0。见http://msdn.microsoft.com/en-us/library/f02979c7.aspx

于 2013-08-14T09:01:34.003 回答
13

来自评论的刺激。答案是否定的。Convert.ToInt32(object)如果没有抛出异常,您将无法执行该操作。你可以做类似的事情(你已经做过了)。我唯一要优化的是value已经是int.

if (value is int) 
    return (int)value;

你不能这样做,Convert.ToInt32(object)因为Convert.ToInt32(object)不简单地测试 if valueisshort, int, long, ushort, ...然后转换它们。它检查是否valueIConvertible。如果是,它使用IConvertible.ToInt32. 可悲的是接口IConvertible很差:它没有非抛出方法(IConvertible.Try*

虽然愚蠢(但可能不会太多),但有人可以制作例如一个UnixDateTime结构:(UnixTime 是从 1970 年 1 月 1 日午夜开始的秒数),其中IConvertible.ToInt32返回这个秒数,而ToString()返回一个格式化的日期。所有的int.TryParse(value.ToString(), out parsed)都会窒息,而Convert.ToInt32会完美地工作。

于 2013-08-14T09:30:29.987 回答
5

无需在这里重新发明轮子。使用int.TryParse来实现您的目标。它返回一个布尔值以显示该值是否已解析。如果解析,结果将保存在输出变量中。

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   
}
于 2013-08-14T09:02:08.000 回答
5

这个使用类型转换器的版本只能作为最后的手段转换为字符串,但也不会抛出异常:

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);
}
于 2016-05-31T11:12:11.927 回答
1

我会混合使用您已经在做的事情;

  • 检查对象是否为 null - 返回 false 和值 0;
  • 尝试直接转换 - 如果成功,则返回 true 和转换后的值
  • 尝试解析 value.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;
}
于 2013-08-14T09:24:12.390 回答
1

返回一个可为空的 int。这样你就知道你是否解析了 0。

int? value = int.TryParse(stringValue, out int outValue) 
    ? outValue
    : default(int?);
于 2018-11-02T15:35:40.660 回答
1

我写了这个烂摊子,看着它让我难过。

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,保持不变。也许对某人有用。

于 2016-09-16T15:23:05.103 回答