55

int.TryPrase is great and all, but there is only one problem...it takes at least two lines of code to use:

int intValue;
string stringValue = "123";
int.TryParse(stringValue, out intValue);
....

Of course I can do something like:

string stringValue = "123";
int intValue = Convert.ToInt32(string.IsNullOrWhiteSpace(stringValue) ? 0 : stringValue); 

on just one line of code.

How can I perform some magic to get int.TryParse to use a one liner, or is there yet a third alternative out there?

Thanks!

Bezden answered the question best, but in reality I plan on using Reddogs solution.

O.O
  • 11,077
  • 18
  • 94
  • 182
  • Whilst a little late to this party...I totally agree, it would be nice to have TryParse as a one liner, but the suggestions here are not very nice. C# 6.0 had a language proposal that would have allowed this syntax... bool result = int.TryParse("123", out int value); // value = 123 – Matthew Layton Jun 29 '16 at 08:28
  • related: if you are casting int to int? you can do `int.TryParse("string", out int result) ? result: result`, so the compiler won't get mad – smurtagh Mar 02 '18 at 16:14

12 Answers12

96
int intValue = int.TryParse(stringValue, out intValue) ? intValue : 0;
Vlad Bezden
  • 83,883
  • 25
  • 248
  • 179
  • 9
    Nice. The only problem, of course, is that you can't differentiate between a bad value and a 0 in the input string... it takes away the point of using TryParse() – James King Jan 06 '11 at 22:23
  • you beat me to it :). +1 for same solution :) – Tomas Jansson Jan 06 '11 at 22:23
  • 2
    @James: I don't agree... that dependes on the context. – Tomas Jansson Jan 06 '11 at 22:24
  • 1
    Well, if the user enters "gobbledygook" in a textbox that expects an int, do you want to blaze ahead using '0' instead? Or do you want to tell the user about their error and let them correct it to get the results they're really after? – James King Jan 06 '11 at 22:28
  • 1
    ...aaaand I just learned you can use a variable as an "out" param in the same line you declare it. Thanks! – Sapph Jan 06 '11 at 22:29
  • 3
    How does this code not scare people? I much prefer @Reddog's extension method. – Joel Rondeau Jan 06 '11 at 22:30
  • Extension methods are generally preferred to a longer line like the one above... but in this case it doesn't take away the issue that you're assigning a default value when the string is invalid. – James King Jan 06 '11 at 22:32
  • @James: Sorry... only thought about the case when input is null :). Think it is time for bed. And I agree with @Joel! – Tomas Jansson Jan 06 '11 at 22:33
  • @Joel, @James: Indeed, you're right in the situations you describe, however, my question is of a less specific nature. – O.O Jan 06 '11 at 22:36
  • I take back my comment about the extension method... I see Reddog is explicitly requiring a default value value for when the conversion fails. Which means the caller is making an active decision to use a default value if the string is invalid. +1 to Reddog – James King Jan 06 '11 at 22:37
  • There are some assumptions made here about how the OP, or anyone else for that mater would want to use the code. Also the question is not about should it be in an extension method or not, the above could equally be encapsulated in an extension method. Using the above with the new C#7 features allowing a variable to be declared inline with the out statement is just what I needed for my linq query. Thanks Vlad – Bronumski May 29 '18 at 19:00
43

Maybe use an extension method:

public static class StringExtensions
{
    public static int TryParse(this string input, int valueIfNotConverted)
    {
        int value;
        if (Int32.TryParse(input, out value))
        {
            return value;
        }
        return valueIfNotConverted;
    }
}

And usage:

string x = "1234";
int value = x.TryParse(0);

Edit: And of course you can add the obvious overload that already sets the default value to zero if that is your wish.

Reddog
  • 15,219
  • 3
  • 51
  • 63
23

This answer is only for those who use at least C# 7.

You can now declare the out parameter inline.

int.TryParse("123", out var result);

Exemplary usage:

if (int.TryParse("123", out var result)) {
    //do something with the successfully parsed integer
    Console.WriteLine(result);
} else {
    Console.WriteLine("That wasn't an integer!");
}

MSDN: https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7#out-variables

taha
  • 722
  • 7
  • 15
Daniel Z.
  • 2,988
  • 2
  • 19
  • 23
4

I would create an extension method out of this.

public static int? AsInt32(this string s)
{
    int value;
    if (int.TryParse(s, out value))
        return value;

    return null;
}
Misha Zaslavsky
  • 8,414
  • 11
  • 70
  • 116
andleer
  • 22,388
  • 8
  • 62
  • 82
2

I don't think there is anything really beautiful, but if you like this you get it down to one row:

string stringValue = "123"
int intValue = int.TryParse(stringValue, out intValue) ? intValue : 0;
Tomas Jansson
  • 22,767
  • 13
  • 83
  • 137
2

One last addition to this NINE year-old question :). Bool parsing is a little different because if parsing fails, you don't want to return a default value, you want to return a NULL. This line does this (as of C# 7, I think):

return bool.TryParse(value, out bool result) ? (bool?)result : null;

That cast of the result is necessary, otherwise it cannot reconcile the differing types of the two return values.

Chris B. Behrens
  • 6,255
  • 8
  • 45
  • 71
1

Check out the StringExtensions class. It contains an AsInt(String,Int32) extension method that will attempt to convert a string and if unsuccessful populate it with the supplied Int32 value as default.

Example:

var intValue = "123".AsInt(-1);
CheckRaise
  • 550
  • 2
  • 16
1
int val2 = "asd".AsInt(-1); 
//Output : -1
 int val3 = "123".AsInt(-1); 
//Output : 123

You need to have System.Web.WebPages namespace.

Damian Kozlak
  • 7,065
  • 10
  • 45
  • 51
CodePunk
  • 11
  • 1
1

In C# 7.0+ you can use inline variable declaration.

  • If parse successes - intValue = its parsed value.
  • If parse fails - intValue = 0.

Code:

int.TryParse(stringValue, out int intValue);

Drawback:

You cannot differentiate between a 0 value and a non parsed value.

Misha Zaslavsky
  • 8,414
  • 11
  • 70
  • 116
0

You do not WANT to make int.TryParse() one line. Why? Because you can't make an assignment to intValue if the input string isn't a valid integer. The whole point of TryParse() is to allow you to test for good input and degrade gracefully, rather than having to catch an exception.

Int.TryParse() is already a shortcut so you don't have to test for a valid int and do the assignment in two steps... that's as far as you want to take it.

James King
  • 6,233
  • 5
  • 42
  • 63
0

Because it essentially returns two values (success and the value), we really do need the two lines.

You could try a wrapper class, ie:

void Main()
{
    var result = simpleIntParser.TryParse("1");
    if(result)
    {
        Console.WriteLine((int)result);
    } else {
        Console.WriteLine("Failed");
    }

    result = simpleIntParser.TryParse("a");
    if(result)
    {
        Console.WriteLine((int)result);
    } else {
        Console.WriteLine("Failed");
    }


}

public class simpleIntParser
{
    public bool result {get; private set;}
    public int value {get; private set;}

    private simpleIntParser(bool result, int value)
    {
        this.result = result;
        this.value = value;
    }

    public static simpleIntParser TryParse(String strValue)
    {
        int value;
        var result = int.TryParse(strValue, out value);
        return new simpleIntParser(result, value);
    }

    public static implicit operator int(simpleIntParser m)
    {
        return m.value;
    }

    public static implicit operator bool(simpleIntParser m)
    {
        return m.result;
    }
}

It requires casting if the type is ambiguous (i.e. for Console.WriteLine()), but if you pass it as an integer parameter for example, no casting is required

Rob
  • 26,989
  • 16
  • 82
  • 98
0

This technically isn't the most efficient as it parses the string twice, but it does get it into one line.
Result as Nullable<int>:

int? ToInt(string value) => int.TryParse(value, out _) ? int.Parse(value) : (int?)null;
Eric
  • 2,207
  • 2
  • 16
  • 16