324 votes

Comment analyser une chaîne de caractères dans un int nullable ?

Je veux analyser une chaîne de caractères dans un int nullable en C#. Je veux récupérer la valeur int de la chaîne ou null si elle ne peut pas être analysée.

J'espérais que ça marcherait

int? val = stringVal as int?;

Mais cela ne fonctionnera pas, donc la façon dont je le fais maintenant est que j'ai écrit cette méthode d'extension

public static int? ParseNullableInt(this string value)
{
    if (value == null || value.Trim() == string.Empty)
    {
        return null;
    }
    else
    {
        try
        {
            return int.Parse(value);
        }
        catch
        {
            return null;
        }
    }
}   

Y a-t-il une meilleure façon de procéder ?

EDITAR: Merci pour les suggestions de TryParse, je connaissais cette méthode, mais elle a fonctionné de la même manière. Je suis plus intéressé par le fait de savoir s'il existe une méthode intégrée dans le framework qui permet d'analyser directement un int nullable ?

1 votes

Vous pouvez utiliser string.IsNullOrEmpty(value) pour rendre la ligne if plus claire.

0 votes

Envisager d'utiliser la conversion générique stackoverflow.com/questions/773078/

374voto

Matt Hamilton Points 98268

int.TryParse est probablement un peu plus facile :

public static int? ToNullableInt(this string s)
{
    int i;
    if (int.TryParse(s, out i)) return i;
    return null;
}

Modifier @Glenn int.TryParse est "intégré au cadre". Il et int.Parse son le site manière d'analyser les chaînes de caractères en ints.

87 votes

Une ligne de moins : return Int32.TryParse(s, out i) ? i : null ;

1 votes

Je préfère nettement cette méthode à celle de TryParse

0 votes

J'étais sur le point de poster un exemple soulignant qu'une NullReferenceException se produirait si la chaîne était nulle. Au lieu de cela, j'ai appris quelque chose d'intéressant sur les méthodes d'extension. string parseOne = "1" ; int ? resultOne = parseOne.ToNullableInt32() ; System.Diagnostics.Debug.Assert(resultOne == 1) ; string parseEmpty = string.Empty ; int ? resultEmpty = parseEmpty.ToNullableInt32() ; System.Diagnostics.Debug.Assert(!resultEmpty.HasValue) ; string parseNull = null ; int ? resultNull = parseNull.ToNullableInt32() ; System.Diagnostics.Debug.Assert(!resultNull.HasValue) ;

199voto

McKenzieG1 Points 5294

Vous pouvez le faire en une seule ligne, en utilisant l'opérateur conditionnel et le fait que vous puissiez lancer l'option null vers un type nullable (deux lignes, si vous n'avez pas un int préexistant que vous pouvez réutiliser pour la sortie de TryParse ) :

Pré C#7 :

int tempVal;
int? val = Int32.TryParse(stringVal, out tempVal) ? Int32.Parse(stringVal) : (int?)null;

Avec la syntaxe actualisée de C#7, qui permet de déclarer une variable de sortie dans l'appel de méthode, cela devient encore plus simple.

int? val = Int32.TryParse(stringVal, out var tempVal) ? tempVal : (int?)null;

2 votes

C'est possible - mais s'appuyer sur les effets secondaires et l'ordre d'évaluation comme cela est désagréable, alors que vous pouvez rendre la dépendance séquentielle évidente en utilisant la syntaxe de Matt. Par ailleurs, il est pratique d'utiliser default(int ?) pour cette expression et d'autres similaires, précisément pour éviter les erreurs d'inférence de type qui découlent de la syntaxe de Matt. null La nature non-typée de l'utilisateur sans avoir besoin d'insérer des casts qui peuvent effectivement exécuter du code.

4 votes

Cela dépend de votre vision de l'opérateur conditionnel, je pense. Mon modèle mental est qu'il s'agit d'une sorte de sucre syntaxique pour l'équivalent if-else, dans ce cas ma version et celle de Matt sont presque identiques, la sienne étant plus explicite, la mienne plus implicite.

11 votes

Il n'y a pas d'effet secondaire d'ordre d'évaluation ici. Toutes les étapes sont explicitement ordonnées et correctes.

39voto

Duckboy Points 227

[ Mise à jour de pour utiliser le C# moderne, conformément à la suggestion de @sblom].

J'ai eu ce problème et je me suis retrouvé avec ceci (après tout, une if et 2 return s est tellement long !) :

int? ToNullableInt (string val)
    => int.TryParse (val, out var i) ? (int?) i : null;

Sur une note plus sérieuse, essayez de ne pas mélanger int qui est un mot-clé du C#, avec Int32 qui est un type de BCL du Framework .NET - bien qu'il fonctionne, il donne au code une apparence désordonnée.

3 votes

Je ne suis pas sûr que cela se traduira par une amélioration des performances une fois la compilation terminée.

1 votes

Encore plus concis en C# 7 : supprimez la balise int i; et aller simplement avec return int.TryParse (val, out var i) ? (int?) i : null;

2 votes

Donc, pour être complet ;-) int? ParseNInt (string val) => int.TryParse (val, out var i) ? (int?) i : null;

16voto

Michael Points 1971

Glenn Slaven : Je suis plus intéressé de savoir si il existe une méthode d'encadrement intégrée qui analysera directement un nullable int ?

Il existe une approche qui analyse directement un int nullable (et pas seulement un int) si la valeur est valide comme null ou une chaîne vide, mais qui lève une exception pour les valeurs invalides. Vous devrez donc attraper l'exception et renvoyer la valeur par défaut pour ces situations :

public static T Parse<T>(object value)
{
    try { return (T)System.ComponentModel.TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value.ToString()); }
    catch { return default(T); }
}

Cette approche peut toujours être utilisée pour les analyses non nulles ainsi que pour les analyses nulles :

enum Fruit { Orange, Apple }
var res1 = Parse<Fruit>("Apple");
var res2 = Parse<Fruit?>("Banana");
var res3 = Parse<int?>("100") ?? 5; //use this for non-zero default
var res4 = Parse<Unit>("45%");

NB : Il existe une méthode IsValid sur le convertisseur que vous pouvez utiliser au lieu de capturer l'exception (les exceptions lancées ont pour résultat frais généraux inutiles si prévu). Malheureusement, il ne fonctionne que depuis .NET 4, mais il y a toujours un problème où il ne vérifie pas votre locale lors de la validation des formats de date et d'heure corrects. bug 93559 .

0 votes

Je l'ai testé pour des entiers et c'est beaucoup plus lent que int.TryParse((string)value, out var result) ? result : default(int ?);

10voto

Joseph Daigle Points 16429

Essayez ça :

public static int? ParseNullableInt(this string value)
{
    int intValue;
    if (int.TryParse(value, out intValue))
        return intValue;
    return null;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X