Home > Enterprise >  What should a method return if it is not an option I want?
What should a method return if it is not an option I want?

Time:12-07

I have this method that takes an array of integers and a target integer.

It should return an array with the 2 indexes of the 2 items in the array that together sum the target value.

public int[] TwoSum(int[] nums, int target)
{
    for (int x = 0; x < nums.Length; x  )
    {
        for (int y = x   1; y < nums.Length; y  )
        {
            if (nums[x]   nums[y] == target) { return new int[] { x, y }; }
        }
    }
}

Example:

Input: nums = [3,2,4], target = 6
Output: [1,2]

My question:

I get an error because not all paths return something. Which is understandable. But what should the method return if it can't find the 2 items?

CodePudding user response:

Option 1: return null.

Oftentimes viewed as dangerous, outdated, "billion-dollar mistake", you name it. But an option nevertheless. Forces the client to perform null-checks, though. More convenient when null actually carries a semantic meaning.

Option 2: empty Array.

"Better" than null but in this case, you'd need to check if it has the desired length, so equally inconvenient for the scenario at hand.

Option 3: bool TryTwoSum( int[] nums, int target, out int[] result )

A common pattern when you do not want to throw exceptions. The result is only considered valid if the function returns true. You'll see it in a lot of TryParse signatures. But this won't help if you must stick with your API.

Option 4: Throw an exception.

Not recommended to control flow. Since not finding a result would not really be an exceptional result, it shouldn't be handled as one. Also, exceptions are considered to be relatively expensive and can be clunky to handle. Among other drawbacks.

An opposing example would be to throw ArgumentNullException if nums is passed as null. That's clearly an exceptional condition that is indicative of a programming error at the client (= caller).

Option 5: return new int[]{-1,-1}

To indicate "no result" without exceptions, without null and with the expected amount of items. A little bit like returning -1 from IndexOf as mentioned in comments by Mong Zhu. Drawback: would really need to be documented because it's not really that obvious that this is how "not found" is represented.

Option 6: A result - object

Basically a wrapper which contains an indicator if the operation has been successful and the result value. This could be implemented in various ways. Either with properties or with polymorphism ... You may have seen this in Web-Controllers for example. May be a little overpowered for this scenario. But can lead to very readable code.


Just to name a few. Which one is correct? That's up to you and your requirements. Some may be more convenient than others for this specific case. There is not one option, that is always the best one.

CodePudding user response:

It's idiomatic in C# that methods that carry a risk of failure can be expressed as "Try..." and return a boolean representing the success (or not) or the method. This reduces the onus of returning any particular int[] value in your case because if the method fails the out argument should be ignored anyway.

static bool TryTwoSum(int[] nums, int target, out int[] xyPair)
{
    for (int x = 0; x < nums.Length; x  )
    {
        for (int y = x   1; y < nums.Length; y  )
        {
            if (nums[x]   nums[y] == target) 
            {
                xyPair = new int[] { x, y };
                return true;
            }
        }
    }
    xyPair = new int[0];
    return false;
}

Usage:

if(TryTwoSum(nums: new[] { 1, 2, 3 }, target: 8, out int[] xyPair))
{
    // ... handle success
}
else
{
    // ... handle failure
}
  • Related