web-dev-qa-db-fra.com

Y at-il un essai Convert.ToInt32 ... en évitant les exceptions

J'aimerais savoir s'il existe un moyen "sûr" de convertir un objet en int, en évitant les exceptions.

Je cherche quelque chose comme public static bool TryToInt32 (valeur d'objet, out int result);

Je sais que je pourrais faire quelque chose comme ça:

    public static bool TryToInt32(object value, out int result)
    {
        try
        {
            result = Convert.ToInt32(value);
            return true;
        }
        catch
        {
            result = 0;
            return false;
        }
    }

Mais je préfère éviter les exceptions, car elles ralentissent le processus.

Je pense que c'est plus élégant, mais c'est quand même "pas cher".

    public static bool TryToInt32(object value, out int result)
    {
        if (value == null)
        {
            result = 0;
            return false;
        }

        return int.TryParse(value.ToString(), out result);
    }

Quelqu'un a une meilleure idée?

METTRE À JOUR:

Cela ressemble un peu à une fente fendue. Mais convertir un objet en chaîne oblige l’implémenteur à créer une fonction ToString () claire.

par exemple:

    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))
        {

        }

Cela ne va pas, je peux faire deux choses ici, ou mettre en œuvre le IConvertable comme ci-dessous.

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

Mais le ToInt32 de l'IConvertible ne peut pas être annulé. Donc, si ce n'est pas possible, une exception ne peut être évitée.

ou deux: existe-t-il un moyen de vérifier si l'objet contient un opérateur implicite?

C'est très pauvre:

        if (value.GetType().GetMethods().FirstOrDefault(method => method.Name == "op_Implicit" && method.ReturnType == typeof(int)) != null)
        {
            result = (int)value;
            return true;
        }
37
J. van Langen
int variable = 0;
int.TryParse(stringValue, out variable);

Si elle ne peut pas être analysée, la variable sera 0. Voir http://msdn.Microsoft.com/en-us/library/f02979c7.aspx

44
ranieuwe

Stimulant des commentaires. La réponse est non . Vous ne pouvez pas faire ce que Convert.ToInt32(object) fait sans avoir levé des exceptions. Vous pouvez faire quelque chose de similaire (et vous l'avez déjà fait). La seule chose que je voudrais optimiser est le cas de value déjà un int.

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

Vous ne pouvez pas faire en tant que Convert.ToInt32(object) car Convert.ToInt32(object) ne vérifie pas simplement si value est short, int, long, ushort, ... et ensuite les jette. Il vérifie si la value est IConvertible. Si oui, il utilise le IConvertible.ToInt32. Malheureusement, l'interface IConvertible est assez pauvre: elle n'a pas de méthodes non-jetables (IConvertible.Try*)

Bien que stupide (mais peut-être pas trop), quelqu'un pourrait créer par exemple une structure UnixDateTime: (UnixTime est le nombre de secondes à partir de minuit le 19/01/01), où IConvertible.ToInt32 renvoie ce nombre de secondes, tandis que ToString() renvoie un rendez-vous amoureux. Tous les int.TryParse(value.ToString(), out parsed) s'étoufferaient, alors que le Convert.ToInt32 fonctionnerait parfaitement.

11
xanatos

Pas besoin de réinventer la roue ici. utilisez int.TryParse pour atteindre votre objectif. Il retourne un bool pour montrer que la valeur est analysée ou non. et si analysé, le résultat est enregistré dans la variable de sortie.

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   
}
7
Ehsan

Cette version utilisant un convertisseur de type ne convertit que chaîne en dernier recours mais ne lève pas non plus d'exception:

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);
}
3
Jeremy Thomas

Je voudrais utiliser un mélange de ce que vous faites déjà;

  • Vérifie si l'objet est null - renvoie false et la valeur 0;
  • Tenter de convertir directement - en cas de succès, renvoyer true et la valeur convertie
  • Tentative d'analyser value.ToString () - si l'opération aboutit, renvoie true et la valeur analysée
  • Tout autre cas - Retourne false et la valeur 0 car l'objet n'est pas convertible/analysable

Le code résultant:

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;
}
1
Lars Kristensen

Retourne un int nullable. Ainsi, vous saurez si vous avez analysé 0.

int? value = int.TryParse(stringValue, out int outValue) 
    ? outValue
    : default(int?);
0
chris31389

J'ai écrit ce gâchis, le regarder me rend triste.

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

Edit Notez maintenant que j'ai répondu en double lorsque la question était int, la gardant de toute façon. Peut-être utile pour quelqu'un.

0
Johan Larsson