Why do all TryParse overloads have an out parameter? [closed]

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?


Solution 1:

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

Solution 2:

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.

Solution 3:

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

Solution 4:

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.