Подтвердить что ты не робот

Есть ли попытка Convert.ToInt32... избежать исключений?

Я хотел бы знать, есть ли "безопасный" способ конвертировать объект в int, исключая исключения.

Я ищу что-то вроде public static bool TryToInt32 (значение объекта, 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);
    }

У кого-нибудь есть идея лучше?

UPDATE:

Это звучит немного как расщепление поиска волос. Но преобразование объекта в строку заставляет разработчика создавать четкую функцию 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;
        }
4b9b3361

Ответ 2

Возвращаясь к комментариям. Ответ нет. Вы не можете делать то, что 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 struct: (UnixTime - это количество секунд с полуночи 1970-01-01), где IConvertible.ToInt32 возвращает это количество секунд, а ToString() возвращает форматированную дату. Все int.TryParse(value.ToString(), out parsed) задохнутся, а Convert.ToInt32 будет работать безупречно.

Ответ 3

Не нужно изобретать колесо здесь. используйте 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   
}

Ответ 4

Эта версия с использованием конвертера типов будет только преобразовывать в строку в качестве последнего средства, но также не вызывать исключения:

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);
}

Ответ 5

Я бы использовал смесь того, что вы уже делаете;

  • Проверьте, является ли объект нулевым - возвращает 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;
}

Ответ 6

Я написал этот беспорядок, глядя на него, и мне грустно.

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, сохраняя его в любом случае. Может быть, полезно для кого-то.