返回空任务或null是否更好?C#

cra*_*eah 8 c# task task-parallel-library

我有一个异步方法,它将通过Api查找作业调度服务的jobId.

如果没有找到结果,那么返回一个空任务或null是否更好?

据我所知,当返回一个集合时,最好返回一个空集合而不是null并使用对象最好返回null而不是空对象; 但对于任务我不确定哪个是最好的.见附件.

谢谢

   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;
    }
Run Code Online (Sandbox Code Playgroud)

Jot*_*aBe 10

Stephen Cleary 的答案完美地解释了这一点:永远不要 return null,否则你会引发空引用异常,但我想添加一些内容:

如果返回 null 而不是已完成的任务,则此代码将引发空引用异常:

await FunctionThatShouldRetunrTaskButReturnsNull();
Run Code Online (Sandbox Code Playgroud)

即使您在调试器中看到它,也很难理解发生了什么。

因此,永远不要null从返回 a 的async函数中返回 a Task

解释:

  • async在返回 aTask或 的非函数中Task<T>,您需要显式创建任务,并且存在返回null而不是任务的危险。
  • async返回 或Task的函数中Task<T>,您只需返回或返回一个值,并且函数的结果会隐式转换为任务,因此不存在返回 的危险null


Ste*_*ary 8

如果没有找到结果,那么返回一个空任务或null是否更好?

这里有几件事需要考虑:

首先,你永远不Task应该返回null.在async世界上,null任务没有意义.Task表示异步方法的执行,因此对于返回null任务的异步方法就像告诉调用代码"你当然没有真正调用此方法"当然.

因此,从方法返回的Task/ Task<T>永远不应该是null.但是,您仍然可以选择在常规任务中返回null .那取决于你.

有任务我不确定哪个是最好的.

任务只是一个包装器.底层逻辑仍然相同.想想这个方法如果是同步的,它会是什么样的; 将您的返回类型int和返回0,如果没有被发现,或者将您的返回类型int?和返回null,如果没有被发现?在为同步方法做出选择之后,将其包装Task<T>为异步方法.

作为最后一点,我必须说:

您的方法可以大大简化:

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;
}
Run Code Online (Sandbox Code Playgroud)

或者,如果要返回以下(而不是任务)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;
}
Run Code Online (Sandbox Code Playgroud)


inf*_*net 6

如果你真的想从异步方法返回 null,你可以使用 Task.FromResult(null)

例如:

public async Task<FileInfo> GetInfo()
{
    return await Task.FromResult<FileInfo>(null);
}
Run Code Online (Sandbox Code Playgroud)