52

I have discovered that many times I don't need the out parameter of the TryParse method, but the problem that it is necessarily. Here I will show one example when it's not needed.

I want to check if a string is an integer, if it is an integer then print "An integer"; otherwise, print "Not an integer". So here is the code:

string value = Console.ReadLine(); //Get a value from the user.
int num; //Why should I have it?? No need at all !

if (int.TryParse(value, out num))
{
    Console.WriteLine("An integer");
}
else
{
    Console.WriteLine("Not an integer");
}

I am just wondering why TryParse always returns an out parameter? Why it doesn't have the overload without an out parameter?

David
  • 208,112
  • 36
  • 198
  • 279
Misha Zaslavsky
  • 8,414
  • 11
  • 70
  • 116
  • 2
    Without knowing for certain I'd imagine it is so you can store the value without having to a second call to Int32.Parse. In the majority of cases I can see you'd want to store the number somewhere. – Andrew Oct 25 '13 at 14:07
  • 3
    Your use case certainly isn't the common case. Normally, when trying to parse an integer, you also want to use the parsed value. That's what the `out` parameter is there for. – Daniel Hilgarth Oct 25 '13 at 14:09
  • 2
    Because the point of it is to parse something from one thing to another... – Liam Oct 25 '13 at 14:09
  • 1
    Apparently you didn't like the right answer (= because it is the whole point of tryParse). Your implicit question I guess that is if you can avoid the out parameter; and I honestly don't see the point of even thinking on doing that: it is just declaring a variable; if you don't want to use its value, don't use it. Pointless question IMO. – varocarbas Oct 25 '13 at 14:12
  • 1
    "Here I will show one example when it's not needed" Got any more examples? – user2586804 Oct 25 '13 at 14:12
  • Because doing same thing twice, once for seeing if it works and second time to actually get the result, is generally a bad thing. – Mat J Oct 25 '13 at 14:13
  • 8
    You're getting a few downvotes, I think it's because of the way you worded the question as if to say "How dare .NET not match my requirements". It's actually not a bad question. – CodingIntrigue Oct 25 '13 at 14:15
  • 1
    This whole question is pointless, you might as well complain about the sky being blue.... – Liam Oct 25 '13 at 14:15
  • 1
    Just because there is no definitive answer doesn't mean the question itself is pointless. It just means the answer is that there is no definitive answer. – CodingIntrigue Oct 25 '13 at 14:18
  • 3
    None of the answers actually explain why the **out** keyword is used, vs. ref or no keyword. – Harrison Oct 25 '13 at 14:21
  • 4
    The question isn't "pointless." I've tested for simply *if* something is numeric (without needing the actual value afterwards) on more than one occasion myself. If it's something you're doing often enough, write a wrapper (extension methods are good for this) and save yourself the typing of a few extra variable declarations. – AllenG Oct 25 '13 at 14:24
  • 1
    @RGraham The fact that there is no definitive answer doesn't make it pointless, but it does make it a bad question *for this site*. If you want to know why Microsoft designed their method, ask them why they did it. Asking a bunch of people who were in no way involved in the decision results in a bunch of guessing, rather than concrete answers, which is not what this site is designed for. – Servy Oct 25 '13 at 14:34
  • @Servy I guess, you're probably right. I always thought the "opinion-based" aspect was to prevent discussions. There can be no "opinions" or "discussions" here, it's a solid answer of "the only people who know aren't going to answer here". Something for meta probably :) – CodingIntrigue Oct 25 '13 at 14:46
  • 2
    @RGraham Yeah, I agree that's not the best reason, but it is the best of what's there, in my eyes. Every single answer that is posted is highly opinion based. While, in theory, an MS employee can give a non-opinion based answer, they aren't here, and everyone else *is* giving opinion based answers. So while the question, technically, doesn't *require* opinion based answers, that's all it will ever get, so that makes the close reason appropriate enough in my eyes. – Servy Oct 25 '13 at 14:48
  • **TryParse** isn't always the correct choice. In the case described above I'd go with **int.parse** and change the **if** to a **try...catch** – Robbie Dee Mar 04 '14 at 16:59
  • @RobbieDee This may be a good answer, but the question is: What is better performance? try catch or tryparse...? – Misha Zaslavsky Mar 04 '14 at 21:06
  • 2
    Exception handling is a more expensive operation. Does this matter? Well it depends where it is in the code. If it is in a loop or a time critical piece of code then perhaps. You might find the annoyance of the dummy variable outweighs the performance hit or vice versa. – Robbie Dee Mar 05 '14 at 08:49
  • Other alternatives will involve using try catch, like @RobbieDee mentioned one of the alternatives and exception handling being an expensive operation. Another way can be `try { Convert.ToInt32(value); Console.WriteLine("Integer"); } catch (FormatException) { Console.WriteLine("Not an integer"); }` – Shishir Gupta Sep 01 '17 at 05:24
  • 1
    We may never know the reason why it's required, but 4 years later, you can save a line of code by doing `int.TryParse("1", out var _);`. ref: https://blogs.msdn.microsoft.com/mazhou/2017/06/27/c-7-series-part-4-discards/ – Ray Cheng Feb 22 '18 at 17:16

4 Answers4

51

Updated Answer:

In more recent versions of C# you can declare the output parameter inline, which allows you to remove the line of code you don't want in your example:

string value = Console.ReadLine(); //Get a value from the user.

if (int.TryParse(value, out int num))
{
    Console.WriteLine("An integer");
}
else
{
    Console.WriteLine("Not an integer");
}

You can simply ignore the result in your code and no longer have that extra line. You still have the extra parameter, but so?

The underlying "why" is still the same and is unlikely to ever change. The method needed to return two things, a bool indicating success and an int indicating the resulting value if successful. (I can't think of another way to convey the result, can you?) Since a method can only return one thing, and a custom result type seems like overkill for this, the decision was made to return the bool and have the result be an out parameter. And once that decision was made, it has to remain for the duration of the language.

"They" certainly could add an overload that doesn't output in the int value. But why? Why expend the effort in designing, documenting, testing, and as we've seen perpetually supporting a method that serves no purpose but to save a few keystrokes for an extreme minority of developers? Again, very unlikely.

For such features you are certainly welcome to propose a change. It would be pretty cool to have a proposal accepted, I imagine. I doubt this one would be, but if you're passionate about it then by all means have at it.


Original Answer:

The short answer is, "Because that's how the method is defined." Perhaps by chance someone from the C# language team might find this question and provide reasoning into why decisions were made, but that doesn't really change much at this point. C# is a statically compiled language and the method signatures need to match, so that's just the way it is.

(Imagine if they changed this and broke .TryParse() on all existing codebases. That would be... bad.)

You might be able to work around this in your own code, though. Something as simple as an extension method could do the trick for you:

public static bool IsInt(this string s)
{
    int x = 0;
    return int.TryParse(s, out x);
}

Then in your code you'd just need to call that method from the string value:

string value = Console.ReadLine();
if (value.IsInt())
    Console.WriteLine("An integer");
else
    Console.WriteLine("Not an integer");
David
  • 208,112
  • 36
  • 198
  • 279
  • 2
    But leads the developer into temptation to use it always even if he plans to use `int.Parse` anyway. – Tim Schmelter Oct 25 '13 at 14:45
  • 2
    @TimSchmelter: It does indeed. Though there's no shortage of incorrect and inefficient things a developer can do in code anyway :) In the OP's example it's not an issue, but mileage may vary in other situations. – David Oct 25 '13 at 14:47
  • @David You just did an extension and the out int is still used, I am not sure what about performance, but I think it is slightly degrades performance. It is more clever to make an extension to the int, but the problem is that you should write all the .net implementation for TryParse but without the out parameter. – Misha Zaslavsky Oct 25 '13 at 17:07
  • @MishaZaslavsky: The `out` parameter is still used because `int.TryParse()` still needs it. This abstracts it behind a method for when your code doesn't need it. As Tim points out, you should still avoid using this extension *in conjunction with* `int.Parse()` as it doubles the effort of parsing the integer. (See his answer for an example.) The alternative here is to write your own version of `.TryParse()` entirely, which probably won't have a high return on investment. At least with this version, the domain-unnecessary `out` parameter is abstracted behind a more domain-appropriate interface. – David Oct 25 '13 at 17:14
  • @David About Tim's answer, it's true, but I can give you many examples that unexperienced may mistake, it's not a reason to remove the option for those who really needs it. I think the best way, is that the visual studio will add an overload without an out parameter one day :) – Misha Zaslavsky Oct 25 '13 at 17:20
  • @MishaZaslavsky: Well, I wouldn't count on that happening. (And it's not Visual Studio, it's the .NET Framework in general.) Barring changes to the `System` API, the next best thing is to abstract it behind domain-specific helpers like this one. – David Oct 25 '13 at 17:39
  • 7
    @MishaZaslavsky I realize this is a very old question, however in C# 7, they added functionality to throw away your out variable using this syntax: int.TryParse(myStr, out _). Obviously, there's still an out variable, but they explicitly made this to represent a parse where you don't care about the result. This clarifies code and is slightly shorter than ", out var num)". – Daniel Ecker Dec 26 '19 at 23:07
7

It has the out parameter because the vast majority of the time when people use it, they want the int (or double, or decimal, or datetime, or whatever) that was parsed.

If you don't want/need the parsed value, and you find yourself doing it all the time, you could write your own "wrapper" on .TryParse() that just takes the string.

In this example (and you could make it more generic, I'm sure) you could do something like

public static bool TryParseNoOutput(this string value)
{
  int noNeed = 0;
  return int.TryParse(value, out noNeed);
}

Then in your code (in this case) you'd call:

string value = Console.ReadLine();
if(value.TryParseNoOutput()) Console.WriteLine("An Integer");
else Console.WriteLine("Not an integer."):

Edit: As has been pointed out in the comments, I tried to call "int.TryParseNoOutput" when I had defined it as an extension on a string. Answer has been updated to reflect that.

AllenG
  • 8,112
  • 29
  • 40
  • 1
    Cool, how did you define a new `static` on `int`? – user2586804 Oct 25 '13 at 14:14
  • 1
    As @user perhaps tries to point out, extension methods operate on an instance, and in your case on a string instance. – CodeCaster Oct 25 '13 at 14:15
  • 1
    @CodeCaster yeah I was having a bit of fun, I knew he couldn't have defined it like that. But it is a million miles from `value.TryParseNoOutput()` – user2586804 Oct 25 '13 at 14:17
  • Whoops. You are correct. I'll fix that right now... – AllenG Oct 25 '13 at 14:18
  • Can I suggest an alternative name that better represents what's being tested? `value.IsInteger()` – user2586804 Oct 25 '13 at 14:21
  • Or `value.CanParseInt()`. Because as is, it no longer says what it is trying to parse it **as**. Is it trying to parse as an `int`, `IPAddress`, `float` or a `DateTime`? Who can tell. – user2586804 Oct 25 '13 at 14:23
  • Yeah, I could change the name, but I figure the OP can figure that out himself. I honestly wouldn't do this at all, since declaring an int isn't actually enough effort to be worth the extension method. I was just showing how it *could* be done. – AllenG Oct 25 '13 at 14:27
6

TryParse is a relatively complex operation to determine the int representation of a string. If there would be an overload that just returns a bool, it would be very likely that many (unexperienced) developers would follow this inefficient pattern:

int myInt = -1;
if(int.TryParse("123"))
    myInt = int.Parse("123");
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • 1
    As long as performance is not your primary concern (and very often it isn't), I don't see any problem here. Without the out parameter you are not forced to introduce a named local variable so you can directly pass the result to another method. This can make your code much more readable in many cases. – lex82 Nov 25 '14 at 09:58
  • @lex82: but `int.Parse` needs to calculate the `int` parameter anyway. So why should it throw away that information? The caller should decide himself if he use it or not. You can even reuse that local variable, for example in a LINQ query. However, you can always write an extension as shown above. – Tim Schmelter Nov 25 '14 at 10:08
  • I think this comes down to a matter of taste. My problem is just that the code is littered with variable declarations -- usually outside of if statements that only use the value in one branch, if at all. I'd rather waste some CPU cycles for the sake of readability. Imagine you could not call HasValue for lifted types without declaring and passing an out parameter. – lex82 Nov 25 '14 at 13:22
  • @lex82: i'd declare variables where as close to where i use them. http://programmers.stackexchange.com/questions/56585/where-do-you-declare-variables-the-top-of-a-method-or-when-you-need-them (not for the reason mentioned there but because of the reason you've mentioned, [here](http://codereview.stackexchange.com/questions/6283/variable-declaration-closer-to-usage-vs-declaring-at-the-top-of-method) is a better example). However, i think i know what you mean, sometimes i also like to remove the local variable and use an extension like [this](http://stackoverflow.com/a/16613455/284240). – Tim Schmelter Nov 25 '14 at 13:34
2

Why does TryParse have an out parameter?
For the very simple reason of how TryParse is implemented.
The way you determine whether or not something is parsable, is by parsing it! If you are able to parse something, then it is parsable. If you cannot parse it, then it is not parsable.

Therefore, by way of determining if something is parsable or not, if it is parsable, then we have already parsed it! It would be silly to throw away this parsed value (anyone who's wondering whether or not something is parsable is likely interested in the parsed result), so the parsed value is returned.

It has an out parameter because the parsed value is a by-product of a true-returning TryParse call.

Task
  • 3,668
  • 1
  • 21
  • 32