如何重构带返回值且会抛出异常的AddAsync异步方法?
解决方案
方法一:使用C# 9.0+的Never返回类型(推荐)
将HandleCreateResponseError的返回类型改为Never,这个类型专门用于标记永远不会正常返回的方法,编译器会自动识别调用该方法后不会继续执行,因此不会再要求返回语句:
// 修改返回类型为 Never private Never HandleCreateResponseError<T>( string propertyName, string id, CreateResponse createResponse) where T : class { Logger.LogError( "An error occurred while adding {0} with {1} = {2}, see debug info: {DebugInformation}", typeof(T).Name, propertyName, id, createResponse.DebugInformation); ThrowElasticException(createResponse); }
修改后,AddAsync方法无需额外改动,编译器会自动消除返回语句缺失的报错。
方法二:兼容旧版C#(无Never类型)
如果项目使用C# 8.0及以下版本,可以让HandleCreateResponseError返回CreateResponse类型,在方法内抛出异常后补充一个永远不会执行的返回语句,最后在AddAsync中返回该方法的调用结果:
// 修改返回类型为 CreateResponse private CreateResponse HandleCreateResponseError<T>( string propertyName, string id, CreateResponse createResponse) where T : class { Logger.LogError( "An error occurred while adding {0} with {1} = {2}, see debug info: {DebugInformation}", typeof(T).Name, propertyName, id, createResponse.DebugInformation); ThrowElasticException(createResponse); // 仅用于满足编译器语法要求,永远不会执行 return createResponse; } // 更新AddAsync的调用逻辑 protected async Task<CreateResponse> AddAsync<T>(T entity, string id) where T : class { var entityId = string.IsNullOrEmpty(id) ? Guid.NewGuid().ToString() : id; var createResponse = await ElasticClient.CreateAsync(entity, c => c .Index(_indexName) .Id(new Id(entityId))); if (createResponse.IsValid) { return createResponse; } // 返回方法调用结果,实际永远不会执行到return return HandleCreateResponseError<T>(entityId, _ => "Id", createResponse); }
方法三:添加不可达代码标记
保持HandleCreateResponseError为void类型,在调用后添加throw new UnreachableException();,明确告知编译器后续代码永远不会执行:
protected async Task<CreateResponse> AddAsync<T>(T entity, string id) where T : class { var entityId = string.IsNullOrEmpty(id) ? Guid.NewGuid().ToString() : id; var createResponse = await ElasticClient.CreateAsync(entity, c => c .Index(_indexName) .Id(new Id(entityId))); if (createResponse.IsValid) { return createResponse; } HandleCreateResponseError<T>(entityId, _ => "Id", createResponse); // 标记该代码永远不会执行,消除编译报错 throw new UnreachableException(); }
内容的提问来源于stack exchange,提问作者Mykyta Butsenko
相关产品推荐
相关产品推荐

