Een string ontleden in een nullable int

Ik wil een string ontleden in een nullable int in C#. d.w.z. Ik wil de int-waarde van de tekenreeks of null terugkrijgen als deze niet kan worden geparseerd.

Ik hoopte eigenlijk dat dit zou werken

int? val = stringVal as int?;

Maar dat zal niet werken, dus zoals ik het nu doe, heb ik deze uitbreidingsmethode geschreven

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

Is er een betere manier om dit te doen?

EDIT:Bedankt voor de TryParse-suggesties, dat wist ik wel, maar het kwam ongeveer op hetzelfde uit. Ik ben meer geïnteresseerd in het weten of er een ingebouwde framework-methode is die direct in een nullable int kan worden geparseerd?


Antwoord 1, autoriteit 100%

int.TryParseis waarschijnlijk een beetje makkelijker:

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

Bewerken@Glenn int.TryParseis “ingebouwd in het raamwerk”. It en int.Parsezijn demanier om strings naar ints te ontleden.


Antwoord 2, autoriteit 54%

Je kunt dit in één regel doen, met behulp van de voorwaardelijke operator en het feit dat je nullnaar een nullable type kunt casten (twee regels, als je geen bestaande int hebt kan hergebruiken voor de uitvoer van TryParse):

Pre C#7:

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

Met de bijgewerkte syntaxis van C#7 waarmee u een uitvoervariabele in de methodeaanroep kunt declareren, wordt dit nog eenvoudiger.

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

Antwoord 3, autoriteit 10%

[Bijgewerktom moderne C# te gebruiken volgens de suggestie van @sblom]

Ik had dit probleem en eindigde met dit (een ifen 2 returns is tenslotte zo langdradig!):

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

Een serieuzere noot: probeer int, wat een C#-sleutelwoord is, niet te mixen met Int32, wat een .NET Framework BCL-type is – hoewel het werkt , het maakt de code alleen maar rommelig.


Antwoord 4, autoriteit 7%

C# >= 7,1

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

Zie C# taalversies om na te gaan welke taalversie uw project ondersteunt


Antwoord 5, autoriteit 4%

Glenn Slaven: Ik ben meer geïnteresseerd om te weten of
er is een ingebouwde raamwerkmethode
dat zal direct ontleden in a
nullable int?

Er is een benadering die direct naar een nullable int (en niet alleen int) zal parseren als de waarde geldig is, zoals null of een lege string, maar een uitzondering genereert voor ongeldige waarden, dus je moet de uitzondering opvangen en retourneren de standaardwaarde voor die situaties:

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

Deze aanpak kan nog steeds worden gebruikt voor niet-nullable parsen en ook voor 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:Er is een IsValid-methode op de converter die u kunt gebruiken in plaats van de uitzondering vast te leggen (gegooide uitzonderingen resulteren in onnodige overheadindien verwacht). Helaas werkt het pas sinds .NET 4, maar er is nog steeds een probleem waarbij het uw landinstelling niet controleert bij het valideren van de juiste DateTime-indelingen, zie bug 93559.


Antwoord 6, autoriteit 3%

Oud onderwerp, maar wat dacht je van:

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

Ik vind dit beter omdat de requriement waar null moet worden geparseerd, de TryParse-versie geen fout zou geven op b.v. ToNullableInt32(XXX). Dat kan ongewenste stille fouten introduceren.


Antwoord 7, autoriteit 3%

Probeer dit:

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

Antwoord 8

Ik vind dat mijn oplossing een zeer schone en mooie oplossing is:

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

Dit is natuurlijk een generieke oplossing die alleen vereist dat het generieke argument een statische methode “Parse(string)” heeft. Dit werkt voor getallen, boolean, DateTime, enz.


Antwoord 9

Je kunt alle andere antwoorden vergeten – er is een geweldige generieke oplossing:
http://cleansharp.de/wordpress/2011/05/generischer-typeconverter/

Hiermee kunt u zeer schone code als volgt schrijven:

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

en ook:

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

10

Ik ben meer geïnteresseerd in het weten of er een ingebouwde kadermethode is die rechtstreeks in een ongeweelbare int zal parseren?

Er is dat niet.


Antwoord 11

Ik heb wat code gevonden en aangepast voor een Generic NullableParser-klasse. De volledige code staat op mijn 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;
        }
    }
}

Antwoord 12

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

Antwoord 13

Je moet nooiteen uitzondering gebruiken als dat niet nodig is – de overhead is verschrikkelijk.

De variaties op TryParse lossen het probleem op – als je creatief wilt zijn (om je code er eleganter uit te laten zien), zou je waarschijnlijk iets kunnen doen met een uitbreidingsmethode in 3.5, maar de code zou min of meer hetzelfde zijn.

p>


Antwoord 14

Met behulp van gedelegeerden kan de volgende code herbruikbaarheid bieden als u merkt dat u de nullable-parsing nodig heeft voor meer dan één structuurtype. Ik heb hier zowel de .Parse() als .TryParse() versies getoond.

Dit is een voorbeeldgebruik:

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

En hier is de code waarmee je daar komt…

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

Antwoord 15

Ik realiseer me dat dit een oud onderwerp is, maar kun je niet gewoon:

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

?


Antwoord 16

Ik heb deze bedacht, die aan mijn eisen voldoet (ik wilde dat mijn extensiemethode zo dicht mogelijk de terugkeer van de TryParse van het framework zou emuleren, maar zonder try{} catch{}-blokken en zonder dat de compiler klaagde over het afleiden van een nullable type binnen de 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;
}

Antwoord 17

Ik stel onderstaande code voor. U mag met uitzondering werken wanneer er een conversiefout is opgetreden.

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

Gebruik deze extensiemethode in code (vul in? Leeftijdseigenschap van een persoonsklasse):

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

OF

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

Antwoord 18

De schonere manier zou zijn om een ​​aparte functie of extensiemethode te schrijven, maar als je alleen een one-liner wilt:

string s;
int? i = s == null ? (int?)null : int.Parse(s);

Other episodes