211

We were discussing with our coworkers on what it means if the method name starts with "Try".

There were the following opinions:

  • Use "Try" when the method can return a null value.
  • Use "Try" when the method will not throw an exception.

What is the official definition? What does "Try" say in the method name? Is there some official guideline about this?

11
  • 91
    +1 People who put this much thought into the names of their functions are actually looking out for "the next guy". Not sure why this is getting close votes (and that's coming from a guy who's cast a lot of them tonight.) Commented Jun 20, 2013 at 7:34
  • 7
    @JonathonReinhart, it got close votes because "As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or specific expertise, but this question will likely solicit debate, arguments, polling, or extended discussion." Commented Jun 20, 2013 at 12:42
  • 19
    There is an official statement by Microsoft that answers the question (see my answer). How is that not a fact? Commented Jun 20, 2013 at 13:15
  • 7
    @PranavHosangadi as Erik mentioned, it is supported by facts. Also, there are plenty of very experienced C# developers here who have specific expertise to provide a valid answer. Hell, Eric Lippert is the chief C# language architect. I think you can call that specific expertise. Commented Jun 20, 2013 at 23:17
  • 4
    @ErikSchierboom That it's the MS guideline is fact. That the MS guideline is the correct guideline to use is subjective and debatable. Commented Jun 21, 2013 at 15:02

6 Answers 6

174

This is known as the TryParse pattern and has been documented by Microsoft. The official Exceptions and Performance MSDN page says:

Consider the TryParse pattern for members that may throw exceptions in common scenarios to avoid performance problems related to exceptions.

Thus if you have code for which a regular use case would mean that it might throw an exception (such as parsing an int), the TryParse pattern makes sense.

Sign up to request clarification or add additional context in comments.

8 Comments

Another useful link that documents this pattern (search for TryParse) blogs.msdn.com/b/kcwalina/archive/2005/03/16/396787.aspx
Basically, if you have a TryParse method, you should have a Parse method that throws when TryParse would return false. Conversely, if you have a Parse method, you should consider having a TryParse method that return false when Parse would throw
+1. Just to add to this, exceptions are generally for "exceptional" circumstances. If you're doing something that could easily fail and that failure is not particularly notable, then using this pattern is more idiomatic than a try/catch
It is basic stuff, but that doesn't mean that guidelines are not useful. Getting basic stuff right can be quite hard if you don't know the platform well enough.
@daveL: It's basic, yes, but a different convention (ParseOrNull and Parse) or even the opposite convention (Parse and ParseOrThrow) would be just as basic. The benefit of guidelines from Microsoft is that it promotes consistency: when you look at a codebase you're not familiar with, you can still understand it, because it (most likely) uses the widespread conventions endorsed by the proprietors of the platform.
|
135

(Corrected) There is official guideline, as Erik suggested.

When I see TrySomething method, I assume it

  • doesn't throw
  • returns bool
  • if I expect value, it is returned via 'out' parameter
  • there exists Something method, that allows me to handle any exception myself. (edit, suggested by Jesse Webb)

5 Comments

Correction - It has official guideline. See Erik's answer.
+1 But I also have a 4th expectation: If there is a TryFoo method, there will be a similar Foo method which allows me to handle any `` exceptions myself. These methods' signatures will likely be different so their usages are not interchangeable without other code changes.
@JesseWebb, thanks for pointing that out. I've added your comment into my answer, if you don't mind.
"Doesn't throw" seems to me overgeneralized. For example, Int32.TryParse(String, NumberStyles, IFormatProvider, Int32) throws ArgumentException if it doesn't like the style parameter.
I agree that "doesn't throw" could be considered overgeneralized, but I believe the intent was to convey that it doesn't throw as a result of execution rather than as a result of the value of the parameters.
10

I think you should use try when you want to proceed. It doesn't matter that a method returns some value or not.

Case 1: if it returns fine, you can proceed in some way.

Case 2: if it does not return: it is still fine; you can proceed in some other way.

And if you expect some value as output of that method then use the out parameter.

Example

int value if (dictionary.TryGetValue("key", out value)) { // Proceed in some way } else { // Proceed in some other way } 

Comments

6

You have to use "Try" in method name, when you want to manifest the fact that the method invokation can produce not valid result. Following the .NET standard it's, by the way, not a function that raises an exception, but the function that returns some VALID or NON_VALID, from the program perspective, value.

At the end, this all about naming convention you decide to use in your group.

Comments

6

Make sure to include try in your methodname if:

  • you don't throw any exception
  • your method has the following signature: bool TrySomething(input, out yourReturn)

So basically if we use try-methods we only get a boolean result back.

So the following code will not throw any exceptions:

string input = "blabla"; int number; if (int.TryParse(input, out number)) { // wooohooo we got an int! } else { //dooh! } 

Whereas this code can (and in this case will) throw exceptions:

string input = "blabla"; int number; try { number = int.Parse(input); //throws an exception } catch (Exception) { //dooh! } 

Using Try methods is a safer and more defensive way to code. Also the code snippet #2 takes more performance to execute if it's not an integer.

4 Comments

Your code snippet #2 should read int number = int.Parse(input); if you want it to be more meaningful in this context.
You are still missing the int number; declaration before the try block and the number = ... assignment.
@PierreArnaud Thank you, I also included 'int number' now.
Note that you may still throw exceptions if the exception is somewhat unrelated to the direct action being performed, like TryLoadFile(path, out file) woah, out of RAM. So the caller would expect no errors for a bad path or access denied, but an exception for the whackier things that could also go wrong. And document it.
2

TLDR:

  • Unless we are talking about TryParse, methods should not start with Try.

  • A method returning null should follow the 'OrDefault' pattern.

  • There is currently no evidence/guidance that the TryParse pattern (which IS documented) was intended to become TryX.

  • TryParse makes sense because there really is only one reason for failure (a bad input string) TrySomething does not make sense if there are multiple reasons for failure and doing so encourages bad error handling.

Explanation

There's an interesting slant to this that I think we have to consider and I think it's a stretch to assume the TryParse pattern can be generaized to TryX. The TryParse pattern as it is named by Microsoft is named specifically with 'Parse' for a reason - using 'TryX' might be considered an anti-pattern and they are trying to avoid expansion of it's use.

If the Tester-Doer pattern tests and then executes, then an execute and then test pattern might be called Doer-Tester. However, there is a fundamental difference. In a Tester-Doer the doer still throws an exception on failure. This is not the case in this TryX Doer-Tester.

This presents a pit-of-success problem. You now have code that might do absolutely nothing. At best you don't know why it failed. In the case of a forgotten if/test, it creates odd, red-herring bugs farther into the code.

I'm not afraid to admit that this is conjecture. But when I first saw "TryParse" as a pattern name, I thought how could they be so lazy and be so specific...and then I thought maybe they weren't.

With parse, there is really a single reason that an exception can be thrown - that the input string was not in the correct format. And so it is understood what a return value of false means.

But in a generic case, that can't be said - there may be multiple failure reasons. You are very quickly getting into other best practice considerations and debates like the case for throwing exceptions and minimizing try/catch blocks and the associated logging.

I'm not saying that there's isn't the occasional application of this 'pattern'. I suppose there are places in background threads and during shutdown or logging attempts where if it goes bad there, your options for recovery grow slim. But these scenarios are pretty rare. And is there really nothing you can do? Are you sure the try/catch shouldn't be higher up? I think those are the questions we're meant to ask before we rely on a pattern that lets us write methods that may or may not do what they are supposed to do.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.