Question

Je suis désireux d'analyser une chaîne de caractères dans un nullable int en C#.c'est à dire.Je veux revenir soit le type int valeur de la chaîne, ou null si il ne peut pas être analysée.

J'ai été un peu en espérant que ce serait le travail

int? val = stringVal as int?;

Mais cela ne marchera pas, donc la façon dont je le fais maintenant c'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;
        }
    }
}   

Est-il une meilleure manière de faire ceci?

EDIT: Merci pour le TryParse suggestions, je n'en sais rien, mais il a travaillé sur le même.Je suis plus intéressé de savoir si il est intégré dans le cadre de la méthode qui permettra d'analyser directement dans un nullable int?

Était-ce utile?

La solution

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é dans le cadre".Et int.Parse sont l' façon d'analyser les chaînes à ints.

Autres conseils

Vous pouvez le faire en une seule ligne, à l'aide de l'opérateur conditionnel et le fait que vous pouvez lancer null pour un type nullable (deux lignes, si vous n'avez pas de pré-existant int vous pouvez les 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 C#7 de la mise à jour de la syntaxe qui permet de déclarer une variable de sortie dans l'appel de méthode, c'est encore plus simple.

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

J'ai eu ce problème j'ai fini avec ce (après tout, un if et 2 returns est soo de longue haleine!):

int? ParseNInt (string 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 .NET Framework type BCL - bien que cela fonctionne, il est tout simplement le code de l'air malpropre.

Glenn Slaven:Je suis plus intéressé dans le fait de savoir si il est intégré dans le cadre de la méthode qui va analyser directement dans un nullable int?

Il est cette approche qui va analyser directement à un nullable int (et pas seulement int) si la valeur est valide comme null ou une chaîne vide, mais ne lève une exception pour les valeurs non valides de sorte que vous aurez besoin pour intercepter l'exception et de retourner 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 encore être utilisé à des fins non nullable analyse ainsi que nullable:

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 y a une méthode IsValid sur le convertisseur, vous pouvez utiliser à la place de la capture de l'exception (les exceptions lancées entraîne surcharge inutile si prévu).Malheureusement, il ne fonctionne que depuis .NET 4, mais il reste un problème où il n'est pas de vérifier vos paramètres régionaux lors de la validation de corriger DateTime les formats, consultez l' bug 93559.

Essayez ceci:

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

Vieux sujet, mais que diriez-vous:

public static int? ParseToNullableInt(this string value)
{
     return String.IsNullOrEmpty(value) ? null : (int.Parse(value) as int?);
}

J'aime mieux cela que le requirement où pour analyser la valeur null, le TryParse version ne serait pas jeter une erreur sur par ex.ToNullableInt32(XXX).Qui peut introduire des silencieux erreurs.

Je sens que ma solution est une très jolie et propre solution:

public static T? NullableParse<T>(string s) where T : struct
{
    try
    {
        return (T)typeof(T).GetMethod("Parse", new[] {typeof(string)}).Invoke(null, new[] { s });
    }
    catch (Exception)
    {
        return null;
    }
}

C'est bien sûr une solution générique qui ne nécessitent que les génériques argument possède une méthode statique "Parse(string)".Cela fonctionne pour les nombres, booléens, DateTime, etc.

var result = int.TryParse(foo, out var f) ? f : default(int?);

Sources:

Vous pouvez oublier toutes les autres réponses - il y a une grande solution générique:http://cleansharp.de/wordpress/2011/05/generischer-typeconverter/

Cela permet d'écrire très propre code comme ceci:

string value = null;
int? x = value.ConvertOrDefault();

et aussi:

object obj = 1;  

string 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();

Les éléments suivants doivent travailler pour n'importe quel type struct.C'est basé sur le code par Matt Manela de forums MSDN.Comme Murph points de la gestion des exceptions pourraient être plus cher par rapport à l'utilisation de Types dédié méthode TryParse.

        public static bool TryParseStruct<T>(this string value, out Nullable<T> result)
            where T: struct 
        {
            if (string.IsNullOrEmpty(value))
            {
                result = new Nullable<T>();

                return true;
            }

            result = default(T);
            try
            {
                IConvertible convertibleString = (IConvertible)value;
                result = new Nullable<T>((T)convertibleString.ToType(typeof(T), System.Globalization.CultureInfo.CurrentCulture));
            }
            catch(InvalidCastException)
            {
                return false;
            }
            catch (FormatException)
            {
                return false;
            }

           return true;
        }

Elles ont été la base des cas de test que j'ai utilisé.

        string parseOne = "1";
        int? resultOne;
        bool successOne = parseOne.TryParseStruct<int>(out resultOne);
        Assert.IsTrue(successOne);
        Assert.AreEqual(1, resultOne);

        string parseEmpty = string.Empty;
        int? resultEmpty;
        bool successEmpty = parseEmpty.TryParseStruct<int>(out resultEmpty);
        Assert.IsTrue(successEmpty);
        Assert.IsFalse(resultEmpty.HasValue);

        string parseNull = null;
        int? resultNull;
        bool successNull = parseNull.TryParseStruct<int>(out resultNull);
        Assert.IsTrue(successNull);
        Assert.IsFalse(resultNull.HasValue);

        string parseInvalid = "FooBar";
        int? resultInvalid;
        bool successInvalid = parseInvalid.TryParseStruct<int>(out resultInvalid);
        Assert.IsFalse(successInvalid);

Je suggère de suivre les méthodes d'extension pour le traitement de chaîne en int valeur avec la possibilité de définir la valeur par défaut dans le cas où l'analyse n'est pas possible:

public static int ParseInt(this string value, int defaultIntValue = 0)
        {
            return int.TryParse(value, out var parsedInt) ? parsedInt : defaultIntValue;
        }

public static int? ParseNullableInt(this string value)
        {
            if (string.IsNullOrEmpty(value))
                return null;

            return value.ParseInt();
        }

Cette solution est générique sans réflexion frais généraux.

public static Nullable<T> ParseNullable<T>(string s, Func<string, T> parser) where T : struct
{
    if (string.IsNullOrEmpty(s) || string.IsNullOrEmpty(s.Trim())) return null;
    else return parser(s);
}

static void Main(string[] args)
{
    Nullable<int> i = ParseNullable("-1", int.Parse);
    Nullable<float> dt = ParseNullable("3.14", float.Parse);
}

Je suis plus intéressé de savoir si il est intégré dans le cadre de la méthode qui permettra d'analyser directement dans un nullable int?

Il n'y en a pas.

J'ai senti que je devais partager le mien qui est un peu plus générique.

Utilisation:

var result = "123".ParseBy(int.Parse);

var result2 = "123".ParseBy<int>(int.TryParse);

Solution:

public static class NullableParse
{
    public static Nullable<T> ParseBy<T>(this string input, Func<string, T> parser)
        where T : struct
    {
        try
        {
            return parser(input);
        }
        catch (Exception exc)
        {
            return null;
        }
    }

    public delegate bool TryParseDelegate<T>(string input, out T result);

    public static Nullable<T> ParseBy<T>(this string input, TryParseDelegate<T> parser)
        where T : struct
    {
        T t;
        if (parser(input, out t)) return t;
        return null;
    }
}

La première version est plus lente, car il nécessite un try-catch mais il a l'air plus propre.Si il ne sera pas appelé à plusieurs reprises avec des chaînes non valides, il n'est pas si important que cela.Si la performance est un problème, veuillez noter que lors de l'utilisation de TryParse méthodes, vous devez spécifier le paramètre de type de ParseBy comme il ne peut pas être déduit par le compilateur.J'ai également eu à définir un délégué comme mot-clé ne peut pas être utilisé à l'intérieur Func<> mais au moins cette fois, le compilateur n'a pas besoin explicite de l'instance.

Enfin, vous pouvez l'utiliser avec d'autres structures ainsi, c'est à diredécimal, DateTime, Guid, etc.

J'ai trouvé et adapté un peu de code pour un Générique NullableParser classe.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
{
    /// <summary>
    /// A parser for nullable types. Will return null when parsing fails.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    ///
    public static class NullableParser<T> where T : struct
    {
        public delegate bool TryParseDelegate(string s, out T result);
        /// <summary>
        /// A generic Nullable Parser. Supports parsing of all types that implements the tryParse method;
        /// </summary>
        /// <param name="text">Text to be parsed</param>
        /// <param name="result">Value is true for parse succeeded</param>
        /// <returns>bool</returns>
        public static bool TryParse(string s, out Nullable<T> result)
        {
            bool success = false;
            try
            {
                if (string.IsNullOrEmpty(s))
                {
                    result = null;
                    success = true;
                }
                else
                {
                    IConvertible convertableString = s as IConvertible;
                    if (convertableString != null)
                    {
                        result = new Nullable<T>((T)convertableString.ToType(typeof(T),
                            CultureInfo.CurrentCulture));
                        success = true;
                    }
                    else
                    {
                        success = false;
                        result = null;
                    }
                }
            }
            catch
            {
                success = false;
                result = null;
            }
            return success;
        }
    }
}
    public static void Main(string[] args)
    {

        var myString = "abc";

        int? myInt = ParseOnlyInt(myString);
        // null

        myString = "1234";

        myInt = ParseOnlyInt(myString);
        // 1234
    }
    private static int? ParseOnlyInt(string s)
    {
        return int.TryParse(s, out var i) ? i : (int?)null;
    }

Vous devriez jamais utiliser une exception si vous n'avez pas à - la surcharge est horrible.

Les variations sur TryParse résoudre le problème - si vous voulez faire preuve de créativité (pour rendre votre code plus élégant), vous pourriez probablement faire quelque chose avec une méthode d'extension en 3.5, mais le code est plus ou moins la même.

À l'aide de délégués, le code suivant est en mesure de fournir la réutilisabilité si vous vous trouvez avoir besoin de la nullable l'analyse de plus d'un type de structure.J'ai montré à la fois les .Parse() et .TryParse() versions ici.

C'est un exemple d'utilisation:

NullableParser.TryParseInt(ViewState["Id"] as string);

Et voici le code qui vous arrive là...

public class NullableParser
  {
    public delegate T ParseDelegate<T>(string input) where T : struct;
    public delegate bool TryParseDelegate<T>(string input, out T outtie) where T : struct;
    private static T? Parse<T>(string input, ParseDelegate<T> DelegateTheParse) where T : struct
    {
      if (string.IsNullOrEmpty(input)) return null;
      return DelegateTheParse(input);
    }
    private static T? TryParse<T>(string input, TryParseDelegate<T> DelegateTheTryParse) where T : struct
    {
      T x;
      if (DelegateTheTryParse(input, out x)) return x;
      return null;
    }
    public static int? ParseInt(string input)
    {
      return Parse<int>(input, new ParseDelegate<int>(int.Parse));
    }
    public static int? TryParseInt(string input)
    {
      return TryParse<int>(input, new TryParseDelegate<int>(int.TryParse));
    }
    public static bool? TryParseBool(string input)
    {
      return TryParse<bool>(input, new TryParseDelegate<bool>(bool.TryParse));
    }
    public static DateTime? TryParseDateTime(string input)
    {
      return TryParse<DateTime>(input, new TryParseDelegate<DateTime>(DateTime.TryParse));
    }
  }

Je suis venu avec celui-ci, qui a satisfait mes besoins (je voulais que ma méthode d'extension pour émuler aussi près que possible le retour du cadre TryParse, mais sans try{} catch{} blocs et sans le compilateur se plaindre de l'inférence de type nullable dans le cadre de la méthode)

private static bool TryParseNullableInt(this string s, out int? result)
{
    int i;
    result = int.TryParse(s, out i) ? (int?)i : null;
    return result != null;
}

Je suggère de code ci-dessous.Vous pouvez collaborer avec d'exception, lorsque convertir erreur s'est produite.

public static class Utils {      
public static bool TryParse<Tin, Tout>(this Tin obj, Func<Tin, Tout> onConvert, Action<Tout> onFill, Action<Exception> 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 string str, Action<int?> onFill, Action<Exception> onError) {
  return Utils.TryParse(str
    , s => string.IsNullOrEmpty(s) ? null : (int?)int.Parse(s)
    , onFill
    , onError);
}
public static bool TryParse(this string str, Action<int> onFill, Action<Exception> onError) {
  return Utils.TryParse(str
    , s => int.Parse(s)
    , onFill
    , onError);
}
}

Utilisez cette méthode d'extension dans le code (remplir les int?L'âge de la propriété d'une personne de la classe):

string 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 sais que c'est un vieux sujet, mais ne pouvez-vous pas tout simplement:

(Nullable<int>)int.Parse(stringVal);

?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top