Paul Turner
Paul Turner

Reputation: 39625

When is a "Try" method preferred over a "null" result?

In the .NET Framework (around the advent of generics), the Try[method] pattern emerged to help deal with the situation where an operation needed to indicate it failed to complete successfully without throwing an exception.

In situations where failure is considered normal (such as parsing) and not exceptional, this is obviously a desirable pattern to follow.

However, if a method can return null to indicate it failed to get a value successfully (such as in the case of a Find method), is this considered more correct than a TryFind method which clearly indicates success or failure with a return value? Is there any precedent set by the .NET Framework to this pattern?

Upvotes: 3

Views: 231

Answers (7)

Rune FS
Rune FS

Reputation: 21742

Quite a few TryParse methods returns Values and not objects meaning they can't return null. Sure with the introduction of Nullable they could be written to return null but null is defined as "no information". In the case of an exception/error that's not semantically correct. Returning true upon succes and false upon failure clearly represent this information. As commented below this also inline with the design of the TryParse method in the .NET framework. They were introduced at the same time as Nullable You also avoid some one using the return value with out checking for null which is easier to do by mistake than to forget to check the result of a TrySomthing method

Upvotes: 1

supercat
supercat

Reputation: 81179

For methods returning class types, I would prefer a TryGetFnord() method which returns null on failure to be preferable to one which returns bool and stores its result in a ref parameter. Among other things, one can include the the former style in a covariant interface, whereas one cannot do so with the latter style. I would suggest keeping the "Try" in the name, however, to indicate that the method could fail.

Another approach to consider would be something like: dataType TryGetFnord(ref TryGetFnordResult result), where TryGetFnordResult could be a value type or immutable class type which indicates whether the operation succeeded. This would preserve the covariance-related advantages while allowing more useful information to be returned than just a pass-fail. In case the operation fails, it should probably return the default value for its type, but the caller should check for failure using the result parameter.

Upvotes: 0

ahawker
ahawker

Reputation: 3374

I believe the TryX pattern pre-dates Nullable<T> types, which were added in .NET 2.0. Nullable<T> solved the problem of value types and the potential discrepancies between whether the default type value was valid/invalid. However, even with these additions, I do believe the TryX pattern still holds value.

The two major benefits of the TryX pattern are:

  • No ambiguity of return value.
  • Safety from exceptions.

Nullable<T> types remove ambiguity but do not provide exception safety.

I don't believe there is a concrete precedence set, but if your method needs to guarantee these, then I would use the TryX pattern.

Upvotes: 2

CodesInChaos
CodesInChaos

Reputation: 108810

  1. Normal value types don't support null. And while there are nullable value types, generics don't support a construct like: Return T? if T is a value type, and T if it's a reference type.
  2. On types supporting null, null is a valid value. Users might want to distinguish between missing entries, and entries that are null.

On the other hand it would be possible to define an Option<T> struct that is returned. Such a type would also be useful in other places(for example optional parameters).


Interestingly the non generic HashTable class return null in its indexer when the element isn't present:

The value associated with the specified key. If the specified key is not found, attempting to get it returns null, and attempting to set it creates a new element using the specified key.

To distinguish between null that is returned because the specified key is not found and null that is returned because the value of the specified key is null, use the Contains method or the ContainsKey method to determine if the key exists in the list.

Upvotes: 2

Oded
Oded

Reputation: 499062

The problem with a null return type is that you need to check for it - this may not be obvious and is easy to forget.

Using a Try* type method makes the flow much clearer.

Having said that, the null object pattern exists exactly because of the issues with returning a null - it allows you to use a "null" object for your type, a valid object that represent a neutral value.

Upvotes: 2

Muad&#39;Dib
Muad&#39;Dib

Reputation: 29226

exceptions should never be used for flow-control or results of a method. of course, there are always exceptions to this rule. this is part of the reason to use TryParse over Try

Upvotes: 0

Jakub Konecki
Jakub Konecki

Reputation: 46008

One reason is when you are returning a struct which cannot be null, ie. double.TryParse().

Upvotes: 0

Related Questions