Frage

Ich möchte eine Zeichenfolge in C# in ein nullbares int analysieren.dh.Ich möchte entweder den int-Wert der Zeichenfolge oder null zurückerhalten, wenn sie nicht analysiert werden kann.

Ich hatte irgendwie gehofft, dass das funktionieren würde

int? val = stringVal as int?;

Aber das wird nicht funktionieren, also mache ich es jetzt so, dass ich diese Erweiterungsmethode geschrieben habe

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

Gibt es einen besseren Weg, dies zu tun?

BEARBEITEN: Vielen Dank für die TryParse-Vorschläge, das wusste ich zwar, aber es hat ungefähr genauso geklappt.Ich bin mehr daran interessiert zu wissen, ob es eine integrierte Framework-Methode gibt, die direkt in ein nullbares int analysiert.

War es hilfreich?

Lösung

int.TryParse ist wahrscheinlich etwas einfacher:

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

Bearbeiten @Glenn int.TryParse ist „in den Rahmen eingebaut“.Es und int.Parse Sind Die Möglichkeit, Strings in Ints zu analysieren.

Andere Tipps

Sie können dies in einer Zeile tun, indem Sie den bedingten Operator und die Tatsache verwenden, dass Sie ihn umwandeln können null zu einem nullbaren Typ (zwei Zeilen, wenn Sie kein bereits vorhandenes int haben, können Sie es für die Ausgabe von wiederverwenden TryParse):

Vor C#7:

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

Mit der aktualisierten Syntax von C#7, die es Ihnen ermöglicht, eine Ausgabevariable im Methodenaufruf zu deklarieren, wird dies noch einfacher.

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

Ich hatte dieses Problem, bei dem ich am Ende dabei war (immerhin ein if und 2 returns ist soo langatmig!):

int? ParseNInt (string val)
{
    int i;
    return int.TryParse (val, out i) ? (int?) i : null;
}

Im Ernst: Versuchen Sie, sich nicht zu vermischen int, ein C#-Schlüsselwort, mit Int32, einem .NET Framework BCL-Typ – obwohl es funktioniert, lässt es den Code nur chaotisch aussehen.

Glenn Slaven:Ich bin mehr daran interessiert zu wissen, ob es eine eingebaute Framework-Methode gibt, die direkt zu einem nullbaren int analysiert wird?

Es gibt diesen Ansatz, der die Analyse direkt in ein nullbares int (und nicht nur int) durchführt, wenn der Wert gültig ist, z. B. null oder eine leere Zeichenfolge, bei ungültigen Werten jedoch eine Ausnahme auslöst, sodass Sie die Ausnahme abfangen und den Standardwert zurückgeben müssen für diese Situationen:

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

Dieser Ansatz kann weiterhin sowohl für nicht-nullable-Analysen als auch für nullable-Analysen verwendet werden:

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%");

Hinweis: Es gibt eine IsValid-Methode im Konverter, die Sie verwenden können, anstatt die Ausnahme zu erfassen (ausgelöste Ausnahmen führen dazu). unnötiger Aufwand wenn erwartet).Leider funktioniert es erst seit .NET 4, aber es gibt immer noch ein Problem, bei dem Ihr Gebietsschema bei der Validierung korrekter DateTime-Formate nicht überprüft wird, siehe Fehler 93559.

Versuche dies:

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

Altes Thema, aber wie wäre es mit:

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

Das gefällt mir besser, da die Anforderung, wo Null analysiert werden soll, die TryParse-Version z. B. beiToNullableInt32(XXX).Dies kann zu unerwünschten stillen Fehlern führen.

Ich finde, meine Lösung ist eine sehr saubere und schöne Lösung:

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

Dies ist natürlich eine generische Lösung, die lediglich erfordert, dass das generische Argument eine statische Methode „Parse(string)“ hat.Dies funktioniert für Zahlen, boolesche Werte, DateTime usw.

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

Quellen:

Alle anderen Antworten können Sie vergessen – es gibt eine tolle generische Lösung:http://cleansharp.de/wordpress/2011/05/generischer-typeconverter/

Dadurch können Sie sehr sauberen Code wie diesen schreiben:

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

und auch:

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

Das Folgende sollte für jeden Strukturtyp funktionieren.Es basiert auf Code von Matt Manela aus MSDN-Foren.Wie Murph betont, könnte die Ausnahmebehandlung im Vergleich zur Verwendung der dedizierten TryParse-Methode von Types teuer sein.

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

Dies waren die grundlegenden Testfälle, die ich verwendet habe.

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

Ich würde die folgenden Erweiterungsmethoden für das Parsen von Zeichenfolgen in einen int-Wert vorschlagen, mit der Möglichkeit, einen Standardwert zu definieren, falls das Parsen nicht möglich ist:

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

Diese Lösung ist generisch und ohne Reflexionsaufwand.

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

Ich bin mehr daran interessiert zu wissen, ob es eine integrierte Framework-Methode gibt, die direkt in ein nullbares int analysiert.

Gibt es nicht.

Ich hatte das Gefühl, ich sollte meinen Beitrag teilen, der etwas allgemeiner ist.

Verwendung:

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

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

Lösung:

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

Die erste Version ist langsamer, da sie einen Try-Catch erfordert, sieht aber sauberer aus.Wenn es nicht oft mit ungültigen Zeichenfolgen aufgerufen wird, ist es nicht so wichtig.Wenn die Leistung ein Problem darstellt, beachten Sie bitte, dass Sie bei der Verwendung von TryParse-Methoden den Typparameter von ParseBy angeben müssen, da dieser vom Compiler nicht abgeleitet werden kann.Ich musste auch einen Delegaten definieren, da das Schlüsselwort out nicht in Func<> verwendet werden kann, aber zumindest erfordert der Compiler dieses Mal keine explizite Instanz.

Schließlich können Sie es auch mit anderen Strukturen verwenden, d. h.Dezimalzahl, DateTime, Guid usw.

Ich habe Code für eine generische NullableParser-Klasse gefunden und angepasst.Den vollständigen Code finden Sie auf meinem 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;
    }

Du solltest niemals Verwenden Sie eine Ausnahme, wenn Sie nicht müssen – der Overhead ist schrecklich.

Die Variationen von TryParse lösen das Problem – wenn Sie kreativ werden möchten (um Ihren Code eleganter aussehen zu lassen), könnten Sie wahrscheinlich etwas mit einer Erweiterungsmethode in 3.5 tun, aber der Code wäre mehr oder weniger derselbe.

Mithilfe von Delegaten kann der folgende Code Wiederverwendbarkeit bieten, wenn Sie die nullfähige Analyse für mehr als einen Strukturtyp benötigen.Ich habe hier sowohl die Versionen .Parse() als auch .TryParse() gezeigt.

Dies ist ein Beispiel für die Verwendung:

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

Und hier ist der Code, der Sie dorthin bringt ...

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

Ich habe mir dieses ausgedacht, das meinen Anforderungen entspricht (ich wollte, dass meine Erweiterungsmethode die Rückgabe von TryParse des Frameworks so genau wie möglich emuliert, aber ohne try{} Catch{}-Blöcke und ohne dass sich der Compiler über die Ableitung von a beschwert nullbarer Typ innerhalb der Framework-Methode)

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

Ich schlage den folgenden Code vor.Sie können mit einer Ausnahme arbeiten, wenn ein Konvertierungsfehler aufgetreten ist.

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

Verwenden Sie diese Erweiterungsmethode im Code (fill int?Alterseigenschaft einer Personenklasse):

string ageStr = AgeTextBox.Text;
Utils.TryParse(ageStr, i => person.Age = i, exc => { MessageBox.Show(exc.Message); });

ODER

AgeTextBox.Text.TryParse(i => person.Age = i, exc => { MessageBox.Show(exc.Message); });

Mir ist klar, dass das ein altes Thema ist, aber können Sie nicht einfach:

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

?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top