115

I am trying to use TryParse to find if the string value is an integer. If the value is an integer then skip foreach loop. Here is my code.

string strValue = "42 "

 if (int.TryParse(trim(strValue) , intVal)) == false
 {
    break;
 }

intVal is a variable of type int?(nullable INT). How can I use Tryparse with nullable int?

Kiquenet
  • 14,494
  • 35
  • 148
  • 243
nav100
  • 1,437
  • 3
  • 13
  • 15

5 Answers5

162

Here's an option for a nullable int with TryParse

public int? TryParseNullable(string val)
{
    int outValue;
    return int.TryParse(val, out outValue) ? (int?)outValue : null;
}
PsychoCoder
  • 10,570
  • 12
  • 44
  • 60
  • 5
    I like this version since "0" returns 0 and "hello" returns null. In the accepted answer, the distinction is lost. – Jeffrey L Whitledge Aug 02 '10 at 19:47
  • 9
    I don't like his answer because it loses the return value indicating the success/failure of the parse. That's an important feature of a Try* method. – frattaro Jul 23 '15 at 12:59
  • 2
    @frattaro I don't really see why this answer could be bad. Try parse returns 0 by default on failure, in this sample it just returns null instead. – Mr. Blond Jun 01 '17 at 15:30
  • @EdgarsŠturms TryParse returns true or false indicating whether or not the operation succeeded. The out parameter gets populated with the parsed value. – frattaro Jun 02 '17 at 16:06
  • 21
    With C#7 it's even easier, no need to have a function, one line is enough : `int? myVal = int.TryParse(toCheck, out int tmp) ? (int?)tmp : null;` – Guillaume Beauvois Oct 10 '17 at 08:04
  • 1
    @frattaro this has an indicator that the parse failed - null. – SixOThree Apr 30 '18 at 19:20
  • @SixOThree In the case of parsing a null string to an int? the output is the same as it would be if the input was "Not An Int". A null string, in my mind, can be parsed as a valid int? whereas the alpha string is not. – frattaro May 01 '18 at 19:37
  • 1
    Good, but violates the Try pattern, should be named `ParseNullable()` instead. – Vedran Mandić Apr 06 '20 at 10:42
88

You can't do this without using another variable, unfortunately - because the type of out arguments has to match the parameter exactly.

Like Daniel's code, but fixed in terms of the second argument, trimming, and avoiding comparisons with Boolean constants:

int tmp;
if (!int.TryParse(strValue.Trim(), out tmp))
{
    break;
}
intVal = tmp;
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • @JonSkeet - strValue cna be null and the Trim() method would result in an exception. Just saying. :) – Shakti Prakash Singh Jun 14 '13 at 12:33
  • 5
    @ShaktiPrakashSingh: We don't know whether `strValue` could be null or not. If it's coming from a text box, it probably *can't* be null. My code doesn't try to address this, but we really don't know whether or not it *should* address it. – Jon Skeet Jun 14 '13 at 17:29
  • 1
    why not reverse the `if`? e.g: `if (int.TryParse(Request["idParent"], out tmp)) idParent = tmp;` (otherwise its null) – Rafael Herscovici Jan 09 '14 at 10:01
  • 7
    @JonSkeet it's worth noting, I think, that while your code matches exactly what the questioner asks (since it's about a loop/break condition most likely), if someone tries to naively adapt this in a non-loop scenario they will end up with 0 as intVal rather than `null` in the case that strValue can't be parsed as an int. Of course, you should never copy/paste from the internet just because an answer is accepted ^_^. – Thomas Jones Jan 15 '15 at 22:59
  • @JonSkeet If you write code that assumes the in parameter is null, you can always write it better, not passing null to functions. Mostly, as already indicated, values comes from text boxes, so they are not null anyway. – Anders Lindén Sep 11 '17 at 12:53
  • 27
    With c#7 it's one line : `int? myVal = int.TryParse(toCheck, out int tmp) ? (int?)tmp : null;` – Guillaume Beauvois Oct 10 '17 at 08:06
26

Could not prevent myself to produce a generic version. Usage below.

    public class NullableHelper
    {
        public delegate bool TryDelegate<T>(string s, out T result);

        public static bool TryParseNullable<T>(string s, out T? result, TryDelegate<T> tryDelegate) where T : struct
        {
            if (s == null)
            {
                result = null;
                return true;
            }

            T temp;
            bool success = tryDelegate(s, out temp);
            result = temp;
            return success;
        }

        public static T? ParseNullable<T>(string s, TryDelegate<T> tryDelegate) where T : struct
        {
            if (s == null)
            {
                return null;
            }

            T temp;
            return tryDelegate(s, out temp)
                       ? (T?)temp
                       : null;
        } 
    }


bool? answer = NullableHelper.ParseNullable<bool>(answerAsString, Boolean.TryParse);
buckley
  • 13,690
  • 3
  • 53
  • 61
6

You could also make an extension method for this purpose;

public static bool TryParse(this object value, out int? parsed)
{
    parsed = null;
    try
    {
        if (value == null)
            return true;

        int parsedValue;
        parsed = int.TryParse(value.ToString(), out parsedValue) ? (int?)parsedValue : null;
        return true;
    }
    catch (Exception)
    {
        return false;
    }
}

I've made this an extension on the object type, but it could equally well be on string. Personally I like these parser-extensions to be available on any object hence the extension on object instead of string.

Example of use:

[TestCase("1", 1)]
[TestCase("0", 0)]
[TestCase("-1", -1)]
[TestCase("2147483647", int.MaxValue)]
[TestCase("2147483648", null)]
[TestCase("-2147483648", int.MinValue)]
[TestCase("-2147483649", null)]
[TestCase("1.2", null)]
[TestCase("1 1", null)]
[TestCase("", null)]
[TestCase(null, null)]
[TestCase("not an int value", null)]
public void Should_parse_input_as_nullable_int(object input, int? expectedResult)
{
    int? parsedValue;

    bool parsingWasSuccessfull = input.TryParse(out parsedValue);

    Assert.That(parsingWasSuccessfull);
    Assert.That(parsedValue, Is.EqualTo(expectedResult));
}

The downside would be that this breaks with the frameworks syntax for parsing values;

int.TryParse(input, out output))

But I like the shorter version of it (whether it's more readable or not might be subject to discussion);

input.TryParse(out output)
Kjetil Klaussen
  • 6,266
  • 1
  • 35
  • 29
  • 1
    If you do this, you're locked into `TryParse` for `int` only. What about `double`? Or `bool`? – FMM Aug 26 '14 at 18:17
  • @FMM a bit late but, write a separate extension method for those if you want them. not sure what you mean "locked in" the other extension methods would have a different signature – Robert Noack Oct 28 '15 at 15:16
  • `T` is implicitly convertible to `T?` for structs. This is overkill. – FMM Oct 28 '15 at 16:11
6

You can create a helper method to parse a nullable value.

Example Usage:

int? intVal;
if( !NullableInt.TryParse( "42", out intVal ) )
{
    break;
}

Helper Method:

public static class NullableInt
{
    public static bool TryParse( string text, out int? outValue )
    {
        int parsedValue;
        bool success = int.TryParse( text, out parsedValue );
        outValue = success ? (int?)parsedValue : null;
        return success;
    }
}
Jerod Houghtelling
  • 4,783
  • 1
  • 22
  • 30