Search code examples
c#tasktask-parallel-library

Is it better to return an empty task or null? c#


I have an asynchronous method which will look for a jobId for a job scheduling service through an Api.

if it finds no results is it better to return an empty task or null?

As i understand when returning a collection it is better to return an empty collection rather than null and using objects its better to return null than an empty object; but with tasks i am unsure which is best. See attached method.

Thank you

   public virtual Task<int> GetJobRunIdAsync(int jobId)
        {
            var jobMonRequest = new jobmonRequest(true, true, true, true, true, 
            true, true, true, true, true, true, true,
            true,
            true, true, true, DateTime.Today, jobId, null, 0, null, null,
            null, null, 0, 0);

        var jobMonResponseTask = Client.jobmonAsync(jobMonRequest);

        var jobTask = jobMonResponseTask.ContinueWith(task =>
        {
            if (jobMonResponseTask.Result == null )
            {
                var empty = new Task<int>(() => 0); // as i understand creating a task with a predefined result will reduce overhead.

                return empty.Result;   // || is it better to just return null?
            }
            if (jobMonResponseTask.Result.jobrun.Length > 1)
            {
                throw  new Exception("More than one job found, Wizards are abound.");
            }
              return jobMonResponseTask.Result.jobrun.Single().id;
        });

        return jobTask;
    }

Solution

  • if it finds no results is it better to return an empty task or null?

    There's a couple things to consider here:

    First, you should never return a null Task. In the async world, a null task just doesn't make sense. Task represents the execution of the asynchronous method, so for an asynchronous method to return a null task is like telling the calling code "you didn't really just call this method" when of course it did.

    So, a Task/Task<T> returned from a method should never, ever be null. However, you still have the option of returning a null value inside a regular task. That is up to you.

    with tasks i am unsure which is best.

    The task is just a wrapper. The underlying logic is still the same. Think of how this method would look if it were synchronous; would your return type be int and return 0 if nothing was found, or would your return type be int? and return null if nothing was found? After making that choice for a synchronous method, then wrap it in Task<T> for the asynchronous method.

    As a final note, I must say:

    Your method can be drastically simplified:

    public virtual async Task<int> GetJobRunIdAsync(int jobId)
    {
      var jobMonRequest = ...;
      var jobMonResponse = await Client.jobmonAsync(jobMonRequest);
      if (jobMonResponse == null)
        return 0;
      if (jobMonResponse.jobrun.Length > 1)
        throw  new Exception("More than one job found, Wizards are abound.");
      return jobMonResponse.jobrun.Single().id;
    }
    

    Or, if you want to return a value (not task) of null:

    public virtual async Task<int?> GetJobRunIdAsync(int jobId)
    {
      var jobMonRequest = ...;
      var jobMonResponse = await Client.jobmonAsync(jobMonRequest);
      if (jobMonResponse == null)
        return null;
      if (jobMonResponse.jobrun.Length > 1)
        throw  new Exception("More than one job found, Wizards are abound.");
      return jobMonResponse.jobrun.Single().id;
    }