Je veux parsingr une chaîne en un entier nullable en C #. c’est à dire. Je veux récupérer la valeur int de la chaîne ou la valeur null si elle ne peut pas être analysée.
J’espérais que cela fonctionnerait
int? val = ssortingngVal as int?;
Mais ça ne marchera pas, alors la façon dont je le fais est que j’ai écrit cette méthode d’extension
public static int? ParseNullableInt(this ssortingng value) { if (value == null || value.Trim() == ssortingng.Empty) { return null; } else { try { return int.Parse(value); } catch { return null; } } }
Existe-t-il une meilleure façon de le faire?
EDIT: Merci pour les suggestions TryParse, je le savais, mais cela a fonctionné de la même manière. Je suis plus intéressé de savoir s’il existe une méthode de framework intégrée qui parsingra directement un int nullable?
int.TryParse
est probablement un peu plus facile:
public static int? ToNullableInt(this ssortingng s) { int i; if (int.TryParse(s, out i)) return i; return null; }
Edit @Glenn int.TryParse
est “intégré au framework”. It et int.Parse
sont le moyen d’parsingr les chaînes en ints.
Vous pouvez le faire en une seule ligne, en utilisant l’opérateur conditionnel et le fait que vous pouvez convertir null
en un type nullable (deux lignes, si vous n’avez pas de int préexistant, vous pouvez le réutiliser pour la sortie de TryParse
):
Pré C # 7:
int tempVal; int? val = Int32.TryParse(ssortingngVal, out tempVal) ? Int32.Parse(ssortingngVal) : (int?)null;
Avec la syntaxe mise à jour de C # 7 qui vous permet de déclarer une variable de sortie dans l’appel de méthode, cela devient encore plus simple.
int? val = Int32.TryParse(ssortingngVal, out var tempVal) ? tempVal : (int?)null;
Désolé, n’a pas pu résister – avait ce problème et Google m’a amené ici, mais je me suis retrouvé avec cela (après tout, un retour si et 2 est tellement long!):
int? ParseNInt (ssortingng val) { int i; return int.TryParse (val, out i) ? (int?) i : null; }
Sur une note plus sérieuse, essayez de ne pas mélanger int , qui est un mot-clé C #, avec Int32 , qui est un type BCL .NET Framework – même si cela fonctionne, le code semble en désordre.
Glenn Slaven : Je suis plus intéressé par le fait de savoir s’il existe une méthode de framework intégrée qui parsingra directement un int nullable?
Il y a cette approche qui parsingra directement un int nul (et pas seulement un int) si la valeur est valide comme une chaîne vide ou vide, mais lance une exception pour les valeurs non valides. Vous devrez donc intercepter l’exception et retourner la valeur par défaut pour ces situations:
public static T Parse(object value) { try { return (T)System.ComponentModel.TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value.ToSsortingng()); } catch { return default(T); } }
Cette approche peut toujours être utilisée pour les parsings non nullables ainsi que pour les valeurs nullables:
enum Fruit { Orange, Apple } var res1 = Parse("Apple"); var res2 = Parse("Banana"); var res3 = Parse("100") ?? 5; //use this for non-zero default var res4 = Parse("45%");
NB: Il existe une méthode IsValid sur le convertisseur que vous pouvez utiliser au lieu de capturer l’exception (les exceptions générées entraînent une surcharge inutile si prévue). Malheureusement, cela ne fonctionne que depuis .NET 4 mais il y a toujours un problème où il ne vérifie pas vos parameters régionaux lors de la validation des formats DateTime corrects, voir le bogue 93559 .
Essaye ça:
public static int? ParseNullableInt(this ssortingng value) { int intValue; if (int.TryParse(value, out intValue)) return intValue; return null; }
Ancien sujet, mais que diriez-vous de:
public static int? ParseToNullableInt(this ssortingng value) { return Ssortingng.IsNullOrEmpty(value) ? null : (int.Parse(value) as int?); }
J’aime mieux cela comme requriement où parsingr NULL, la version TryParse ne jetterait pas d’erreur, par exemple sur ToNullableInt32 (XXX). Cela peut introduire des erreurs silencieuses indésirables.
Je pense que ma solution est une solution très propre et agréable:
public static T? NullableParse(ssortingng s) where T : struct { try { return (T)typeof(T).GetMethod("Parse", new[] {typeof(ssortingng)}).Invoke(null, new[] { s }); } catch (Exception) { return null; } }
C’est bien sûr une solution générique qui nécessite uniquement que l’argument des génériques ait une méthode statique “Parse (ssortingng)”. Cela fonctionne pour les nombres, booléens, DateTime, etc.
Vous pouvez oublier toutes les autres réponses – il existe une excellente solution générique: http://cleansharp.de/wordpress/2011/05/generischer-typeconverter/
Cela vous permet d’écrire du code très propre comme ceci:
ssortingng value = null; int? x = value.ConvertOrDefault();
et aussi:
object obj = 1; ssortingng value = null; int x = 5; if (value.TryConvert(out x)) Console.WriteLine("TryConvert example: " + x); bool boolean = "false".ConvertOrDefault(); bool? nullableBoolean = "".ConvertOrDefault(); int integer = obj.ConvertOrDefault(); int negativeInteger = "-12123".ConvertOrDefault(); int? nullableInteger = value.ConvertOrDefault(); MyEnum enumValue = "SecondValue".ConvertOrDefault(); MyObjectBase myObject = new MyObjectClassA(); MyObjectClassA myObjectClassA = myObject.ConvertOrDefault();
Ce qui suit devrait fonctionner pour tout type de structure. Il est basé sur le code par Matt Manela des forums MSDN . Comme le fait remarquer Murph, la gestion des exceptions peut être coûteuse par rapport à l’utilisation de la méthode TryParse dédiée à Types.
public static bool TryParseStruct(this ssortingng value, out Nullable result) where T: struct { if (ssortingng.IsNullOrEmpty(value)) { result = new Nullable (); return true; } result = default(T); try { IConvertible convertibleSsortingng = (IConvertible)value; result = new Nullable ((T)convertibleSsortingng.ToType(typeof(T), System.Globalization.CultureInfo.CurrentCulture)); } catch(InvalidCastException) { return false; } catch (FormatException) { return false; } return true; }
Ce sont les cas de test de base que j’ai utilisés.
ssortingng parseOne = "1"; int? resultOne; bool successOne = parseOne.TryParseStruct(out resultOne); Assert.IsTrue(successOne); Assert.AreEqual(1, resultOne); ssortingng parseEmpty = ssortingng.Empty; int? resultEmpty; bool successEmpty = parseEmpty.TryParseStruct (out resultEmpty); Assert.IsTrue(successEmpty); Assert.IsFalse(resultEmpty.HasValue); ssortingng parseNull = null; int? resultNull; bool successNull = parseNull.TryParseStruct (out resultNull); Assert.IsTrue(successNull); Assert.IsFalse(resultNull.HasValue); ssortingng parseInvalid = "FooBar"; int? resultInvalid; bool successInvalid = parseInvalid.TryParseStruct (out resultInvalid); Assert.IsFalse(successInvalid);
Cette solution est générique sans surcharge de reflection.
public static Nullable ParseNullable (ssortingng s, Func parser) where T : struct { if (ssortingng.IsNullOrEmpty(s) || ssortingng.IsNullOrEmpty(s.Trim())) return null; else return parser(s); } static void Main(ssortingng[] args) { Nullable i = ParseNullable("-1", int.Parse); Nullable dt = ParseNullable("3.14", float.Parse); }
Je suis plus intéressé de savoir s’il existe une méthode de framework intégrée qui parsingra directement un int nullable?
Il n’y en a pas.
Je sentais que je devais partager le mien qui est un peu plus générique.
Usage:
var result = "123".ParseBy(int.Parse); var result2 = "123".ParseBy(int.TryParse);
Solution:
public static class NullableParse { public static Nullable ParseBy (this ssortingng input, Func parser) where T : struct { try { return parser(input); } catch (Exception exc) { return null; } } public delegate bool TryParseDelegate (ssortingng input, out T result); public static Nullable ParseBy (this ssortingng input, TryParseDelegate parser) where T : struct { T t; if (parser(input, out t)) return t; return null; } }
La première version est plus lente car elle nécessite un try-catch mais elle semble plus propre. S’il n’est pas appelé plusieurs fois avec des chaînes non valides, ce n’est pas important. Si les performances posent problème, notez que lorsque vous utilisez les méthodes TryParse, vous devez spécifier le paramètre type de ParseBy, car il ne peut pas être déduit par le compilateur. J’ai également dû définir un délégué car le mot-clé out ne peut pas être utilisé dans Func <>, mais au moins cette fois le compilateur ne nécessite pas d’instance explicite.
Enfin, vous pouvez également l’utiliser avec d’autres structures, par exemple décimales, DateHeure, Guid, etc.
J’ai trouvé et adapté du code pour une classe NullableParser générique. Le code complet est sur mon blog Nullable TryParse
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Globalization; namespace SomeNamespace { /// /// A parser for nullable types. Will return null when parsing fails. /// /// /// public static class NullableParser where T : struct { public delegate bool TryParseDelegate(ssortingng s, out T result); /// /// A generic Nullable Parser. Supports parsing of all types that implements the tryParse method; /// /// Text to be parsed /// Value is true for parse succeeded /// bool public static bool TryParse(ssortingng s, out Nullable result) { bool success = false; try { if (ssortingng.IsNullOrEmpty(s)) { result = null; success = true; } else { IConvertible convertableSsortingng = s as IConvertible; if (convertableSsortingng != null) { result = new Nullable ((T)convertableSsortingng.ToType(typeof(T), CultureInfo.CurrentCulture)); success = true; } else { success = false; result = null; } } } catch { success = false; result = null; } return success; } } }
Je suis venu avec celui-ci, qui a satisfait mes exigences (je voulais que ma méthode d’extension émule au plus près le retour de TryParse du framework, mais sans try {} catch {} blocks et sans que le compilateur se moque d’inférer un type nullable dans la méthode framework
private static bool TryParseNullableInt(this ssortingng s, out int? result) { int i; result = int.TryParse(s, out i) ? (int?)i : null; return result != null; }
public static void Main(ssortingng[] args) { var mySsortingng = "abc"; int? myInt = ParseOnlyInt(mySsortingng); // null mySsortingng = "1234"; myInt = ParseOnlyInt(mySsortingng); // 1234 } private static int? ParseOnlyInt(ssortingng s) { return int.TryParse(s, out var i) ? i : (int?)null; }
Je suggère de suivre les méthodes d’extension pour l’parsing de chaîne dans int value avec la possibilité de définir la valeur par défaut si l’parsing syntaxique n’est pas possible:
public static int ParseInt(this ssortingng value, int defaultIntValue = 0) { return int.TryParse(value, out var parsedInt) ? parsedInt : defaultIntValue; } public static int? ParseNullableInt(this ssortingng value) { if (ssortingng.IsNullOrEmpty(value)) return null; return value.ParseInt(); }
Vous ne devriez jamais utiliser une exception si vous n’êtes pas obligé – la surcharge est horrible.
Les variantes de TryParse résolvent le problème – si vous voulez être créatif (pour rendre votre code plus élégant), vous pouvez probablement faire quelque chose avec une méthode d’extension au 3.5 mais le code sera plus ou moins le même.
À l’aide de delegates, le code suivant est capable de fournir une possibilité de réutilisation si vous avez besoin de l’parsing nullable pour plusieurs types de structure. J’ai montré les versions .Parse () et .TryParse () ici.
Ceci est un exemple d’utilisation:
NullableParser.TryParseInt(ViewState["Id"] as ssortingng);
Et voici le code qui vous y mène …
public class NullableParser { public delegate T ParseDelegate(ssortingng input) where T : struct; public delegate bool TryParseDelegate (ssortingng input, out T outtie) where T : struct; private static T? Parse (ssortingng input, ParseDelegate DelegateTheParse) where T : struct { if (ssortingng.IsNullOrEmpty(input)) return null; return DelegateTheParse(input); } private static T? TryParse (ssortingng input, TryParseDelegate DelegateTheTryParse) where T : struct { T x; if (DelegateTheTryParse(input, out x)) return x; return null; } public static int? ParseInt(ssortingng input) { return Parse(input, new ParseDelegate (int.Parse)); } public static int? TryParseInt(ssortingng input) { return TryParse (input, new TryParseDelegate (int.TryParse)); } public static bool? TryParseBool(ssortingng input) { return TryParse(input, new TryParseDelegate (bool.TryParse)); } public static DateTime? TryParseDateTime(ssortingng input) { return TryParse(input, new TryParseDelegate (DateTime.TryParse)); } }
Je suggère un code ci-dessous. Vous pouvez travailler avec une exception, lorsque l’erreur de conversion s’est produite.
public static class Utils { public static bool TryParse(this Tin obj, Func onConvert, Action onFill, Action onError) { Tout value = default(Tout); bool ret = true; try { value = onConvert(obj); } catch (Exception exc) { onError(exc); ret = false; } if (ret) onFill(value); return ret; } public static bool TryParse(this ssortingng str, Action onFill, Action onError) { return Utils.TryParse(str , s => ssortingng.IsNullOrEmpty(s) ? null : (int?)int.Parse(s) , onFill , onError); } public static bool TryParse(this ssortingng str, Action onFill, Action onError) { return Utils.TryParse(str , s => int.Parse(s) , onFill , onError); } }
Utilisez cette méthode d’extension dans le code (propriété fill int? Age d’une classe de personne):
ssortingng ageStr = AgeTextBox.Text; Utils.TryParse(ageStr, i => person.Age = i, exc => { MessageBox.Show(exc.Message); });
OU
AgeTextBox.Text.TryParse(i => person.Age = i, exc => { MessageBox.Show(exc.Message); });
Je réalise que c’est un vieux sujet, mais ne pouvez-vous pas simplement:
(Nullable)int.Parse(ssortingngVal);
?