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;
}
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
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.
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
}
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);
}
Je voudrais utiliser un mélange de ce que vous faites déjà;
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;
}
Retourne un int nullable. Ainsi, vous saurez si vous avez analysé 0.
int? value = int.TryParse(stringValue, out int outValue)
? outValue
: default(int?);
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.