从可能执行异步调用的方法中简单退出
Trivial exit from an method that may perform an asynchronous call
我在调用可能 return Task<T>
或 null
的方法时遇到问题,具体取决于初始同步查找调用的结果(这本身可能是反-模式所以请告诉我)。
如果出现简单的退出条件,我有点想 return null
但这会导致调用(外部)方法失败,因为外部调用需要 Task<T>
响应(琐碎的出口)被推到 ConfigureAwait(true)
随后产生 NullReferenceException
.
外调用方式:
var res = await MyService.GetUserCourseStatusAsync(userID, productID).ConfigureAwait(true);
中间方法:
public Task<IGetUserCourseResponse> GetUserCourseStatusAsync(int userID, int productID)
{
// Look up User's ID (if exists)
var userCredentials = GetUserCredentials(userID);
if (userCredentials?.UserID == null)
return null; // Trivial return of null ("User not registered"). *** This causes exception on ConfigureAwait(true) above ***
// Another synchronous call
var courseId = GetCourseID(productID);
if (courseId == null)
throw new InvalidOperationException($"Product #{productID} is not a course");
// Asynchronous call to inner method (this bit works fine)
return GetUserCourseAsync(userCredentials.UserID.Value, courseId.Value);
}
所以我当时的想法是我们应该总是 return 一个 Task<T>
而不是 null
。
但是,所有这些都会导致编译错误:
//return null; // Trivial return of null ("User not registered"). *** This causes exception
// Compile error: CS0029: Cannot implicitly convert type 'GetUserCourseInner' to 'System.Threading.Tasks.Task<IGetUserCourseResponse>'
return new GetUserCourseInner(); // Not registered
// Compile error: CS1503 Argument 1: cannot convert from 'GetUserCourseInner' to 'System.Func<IGetUserCourseResponse>'
return new Task<IGetUserCourseResponse>(new GetUserCourseInner()); // Not registered
如何 return 不是异步调用结果的虚拟 Task<T>
?
这是正确的方法吗?
如您所建议,return 一个 Task<IGetUserCourseResponse>
包含 null
(或其他标记值)会更好.您可以创建这样一个完整的 Task
with Task.FromResult((IGetUserCourseResponse)null)
:
public Task<IGetUserCourseResponse> GetUserCourseStatusAsync(int userID, int productID)
{
// Look up User's ID (if exists)
var userCredentials = GetUserCredentials(userID);
if (userCredentials?.UserID == null)
return Task.FromResult((IGetUserCourseResponse)null);
// Another synchronous call
var courseId = GetCourseID(productID);
if (courseId == null)
throw new InvalidOperationException($"Product #{productID} is not a course");
// Asynchronous call to inner method (this bit works fine)
return GetUserCourseAsync(userCredentials.UserID.Value, courseId.Value);
}
或者,您可以创建外部方法 async
。 注意 但是,这会在抛出 InvalidOperationException
的情况下改变其行为:而不是直接抛出此异常的方法,而是 return a Task
其中包含此异常。这个不一定是你想要的:
public async Task<IGetUserCourseResponse> GetUserCourseStatusAsync(int userID, int productID)
{
// Look up User's ID (if exists)
var userCredentials = GetUserCredentials(userID);
if (userCredentials?.UserID == null)
return null;
// Another synchronous call
var courseId = GetCourseID(productID);
if (courseId == null)
throw new InvalidOperationException($"Product #{productID} is not a course");
// Asynchronous call to inner method (this bit works fine)
return await GetUserCourseAsync(userCredentials.UserID.Value, courseId.Value);
}
只是 return 一个包含空值作为结果的任务
return Task.FromResult<IGetUserCourseResponse>(null);
我在调用可能 return Task<T>
或 null
的方法时遇到问题,具体取决于初始同步查找调用的结果(这本身可能是反-模式所以请告诉我)。
如果出现简单的退出条件,我有点想 return null
但这会导致调用(外部)方法失败,因为外部调用需要 Task<T>
响应(琐碎的出口)被推到 ConfigureAwait(true)
随后产生 NullReferenceException
.
外调用方式:
var res = await MyService.GetUserCourseStatusAsync(userID, productID).ConfigureAwait(true);
中间方法:
public Task<IGetUserCourseResponse> GetUserCourseStatusAsync(int userID, int productID)
{
// Look up User's ID (if exists)
var userCredentials = GetUserCredentials(userID);
if (userCredentials?.UserID == null)
return null; // Trivial return of null ("User not registered"). *** This causes exception on ConfigureAwait(true) above ***
// Another synchronous call
var courseId = GetCourseID(productID);
if (courseId == null)
throw new InvalidOperationException($"Product #{productID} is not a course");
// Asynchronous call to inner method (this bit works fine)
return GetUserCourseAsync(userCredentials.UserID.Value, courseId.Value);
}
所以我当时的想法是我们应该总是 return 一个 Task<T>
而不是 null
。
但是,所有这些都会导致编译错误:
//return null; // Trivial return of null ("User not registered"). *** This causes exception
// Compile error: CS0029: Cannot implicitly convert type 'GetUserCourseInner' to 'System.Threading.Tasks.Task<IGetUserCourseResponse>'
return new GetUserCourseInner(); // Not registered
// Compile error: CS1503 Argument 1: cannot convert from 'GetUserCourseInner' to 'System.Func<IGetUserCourseResponse>'
return new Task<IGetUserCourseResponse>(new GetUserCourseInner()); // Not registered
如何 return 不是异步调用结果的虚拟 Task<T>
?
这是正确的方法吗?
如您所建议,return 一个 Task<IGetUserCourseResponse>
包含 null
(或其他标记值)会更好.您可以创建这样一个完整的 Task
with Task.FromResult((IGetUserCourseResponse)null)
:
public Task<IGetUserCourseResponse> GetUserCourseStatusAsync(int userID, int productID)
{
// Look up User's ID (if exists)
var userCredentials = GetUserCredentials(userID);
if (userCredentials?.UserID == null)
return Task.FromResult((IGetUserCourseResponse)null);
// Another synchronous call
var courseId = GetCourseID(productID);
if (courseId == null)
throw new InvalidOperationException($"Product #{productID} is not a course");
// Asynchronous call to inner method (this bit works fine)
return GetUserCourseAsync(userCredentials.UserID.Value, courseId.Value);
}
或者,您可以创建外部方法 async
。 注意 但是,这会在抛出 InvalidOperationException
的情况下改变其行为:而不是直接抛出此异常的方法,而是 return a Task
其中包含此异常。这个不一定是你想要的:
public async Task<IGetUserCourseResponse> GetUserCourseStatusAsync(int userID, int productID)
{
// Look up User's ID (if exists)
var userCredentials = GetUserCredentials(userID);
if (userCredentials?.UserID == null)
return null;
// Another synchronous call
var courseId = GetCourseID(productID);
if (courseId == null)
throw new InvalidOperationException($"Product #{productID} is not a course");
// Asynchronous call to inner method (this bit works fine)
return await GetUserCourseAsync(userCredentials.UserID.Value, courseId.Value);
}
只是 return 一个包含空值作为结果的任务
return Task.FromResult<IGetUserCourseResponse>(null);