views:

8412

answers:

11

I'm wanting to parse a string into a nullable int in C#. ie. I want to get back either the int value of the string or null if it can't be parsed.

I was kind of hoping that this would work

int? val = stringVal as int?;

But that won't work, so the way I'm doing it now is I've written this extension method

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 there a better way of doing this?

EDIT: Thanks for the TryParse suggestions, I did know about that, but it worked out about the same. I'm more interested in knowing if there is a built-in framework method that will parse directly into a nullable int?

+50  A: 

Int32.TryParse is probably a tad easier:

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

Edit @Glenn Int32.TryParse is "built into the framework". It and Int32.Parse are the way to parse strings to ints.

Matt Hamilton
one less line: return Int32.TryParse(s, out i) ? i : null;
Chris Shouts
I definitely prefer this way to TryParse
Bent Rasmussen
I was about to post an example pointing out that a NullReferenceException would occur if the string was null. Instead I learned something interesting about extension methods.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);
Daniel Ballinger
+3  A: 

Try this:

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

I probably would just use the try/catch part that you have there, but I like Matt Hamilton's method aswell.

AlexCuse
+14  A: 

You can do this in one line, using the conditional operator and the fact that you can cast null to a nullable type (two lines, if you don't have a pre-existing int you can reuse for the output of TryParse):

int tempVal;
int? val = Int32.TryParse(stringVal, out tempVal) ? tempVal : (int?)null;
McKenzieG1
You could - but relying on side-effects and order-of-evaluation like that is nasty, when you can make the sequential dependancy obvious by using Matt's syntax.Incidentally, it's handy to use default(int?) for this and similar expressions precisely to avoid the type-inference errors that stem from `null`'s untyped nature without needing to insert casts that may actually execute code.
Eamon Nerbonne
That depends on your view of the conditional operator, I think. My mental model is that it is pretty much syntactic sugar for the if-else equivalent, in which case my version and Matt's are close to identical, with his being more explicit, mine more cmopact.
McKenzieG1
A: 

You should never use an exception if you don't have to - the overhead is horrible.

The variations on TryParse solve the problem - if you want to get creative (to make your code look more elegant) you could probably do something with an extension method in 3.5 but the code would be more or less the same.

Murph
+7  A: 

Sorry, couldn't resist - had this problem and Google brought me here, but I ended up with this (after all, an if and 2 returns is soo long-winded!):

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

On a more serious note, try not to mix int, which is a C# keyword, with Int32, which is a .NET Framework BCL type - although it works, it just makes code look messy.

Duckboy
i *love* this solution!
Evildonald
A: 

I'm more interested in knowing if there is a built-in framework method that will parse directly into a nullable int?

There isn't.

Orion Edwards
A: 

Using delegates, the following code is able to provide reusability if you find yourself needing the nullable parsing for more than one structure type. I've shown both the .Parse() and .TryParse() versions here.

This is an example usage:

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

And here is the code that gets you there...

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));
    }
  }
umbyersw
A: 

I found and adapted some code for a Generic NullableParser class. The full code is on my blog Nullable TryParse

John Dauphine
A: 

I realise this is an old topic, but can't you simply:

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

?

Milky Joe
A: 

The following should work for any struct type. It is based off code by Matt Manela from MSDN forums. As Murph points out the exception handling could be expensive compared to using the Types dedicated TryParse method.

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

These were the basic test cases I used.

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