C# 9+ 中的 HttpClient 空警告
Posted
技术标签:
【中文标题】C# 9+ 中的 HttpClient 空警告【英文标题】:HttpClient null warning in C# 9+ 【发布时间】:2021-12-14 10:33:10 【问题描述】:我刚刚将 .NET3.1 应用程序迁移到 .NET6(我使用的是 VS 2022),我注意到他们引入了一些与可空类型相关的约束。我修复了所有代码以遵循最佳实践,但不确定如何解决此问题:
当创建一个新的 HttpClient 实例时,它返回一个可为空的 HttpClient 类型(代码在 Polly 重试策略中执行):
public async Task<List<InterestedParty>> GetInterestedPartiesAsync()
return await _retryPolicy.ExecuteAsync(async () =>
using var client = new HttpClient()
const string endpoint = "my-endpoint";
var url = $"endpoint/test";
var response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
var jsonString = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<List<InterestedParty>>(jsonString);
);
编译器抱怨可能返回空引用。 我知道我可以使用以下命令来抑制警告:
#pragma warning disable CS8603 // Possible null reference return.
但我认为这不是最好的解决方案。
还有其他建议吗?谢谢。
【问题讨论】:
你的方法实际返回是什么?不是HttpClient
,我接受。从字面上看,这个警告当然是无稽之谈——new
不会返回null
。不过,我怀疑这不是警告的内容(看看所有其他的也是弯曲的)。忽略var
上的类型提示,这是另一回事。
IntelliSense 建议修复什么?
请给我们完整的代码,代码截图大多没用。此外,请确保您包含足够的上下文,以便我们可以复制它。基本上我们需要一个minimal reproducible example
尽管如此 - 你真的不应该在每个请求上都创建 HttpClient。处理 HttpClient 的正确方法是存储单个静态引用或使用 HttpClientFactory。我真的不能足够强调这是多么重要。更多详情:aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
@DragosStoica 是唯一的外部调用,但是这个调用执行了多少次?当然,您不想每次都创建一个新实例,这会影响性能,并且您可能会在此过程中遇到一些错误,因为 http 客户端不是以这种方式使用的。
【参考方案1】:
问题本身与我一开始认为的 HttpClient 无关。
方法的返回类型是 Task 并且在我返回的 using 语句中
JsonConvert.DeserializeObject<List<InterestedParty>>(jsonString);
事实上,反序列化的对象可以为 null,因此一种解决方案是在末尾添加“null forgiving”运算符 (!):
public async Task<List<InterestedParty>> GetInterestedPartiesAsync()
return await _retryPolicy.ExecuteAsync(async () =>
using var client = new HttpClient();
const string endpoint = "my-endpoint";
var url = $"endpoint/test";
var response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
var jsonString = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<List<InterestedParty>>(jsonString)!;
);
另一个更好的建议是:
public async Task<IEnumerable<InterestedParty>> GetInterestedPartiesAsync()
return await _retryPolicy.ExecuteAsync(async () =>
using var client = new HttpClient();
const string endpoint = "my-endpoint";
var url = $"endpoint/test";
var response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
var jsonString = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<List<InterestedParty>>(jsonString) ??
Enumerable.Empty<InterestedParty>();
);
感谢@JeroenMostert 和@DavidG 的建议。
【讨论】:
我认为这不是解决问题的正确方法。Null forgiving
运算符应该很少使用,几乎从不使用 - 它不是为了解决这些问题。更好的方法是返回Task<List<InterestedParty>?>
或者,根据你的数据模型,返回?? new List<InterestedParty>()
;空集合通常比null
好,因为它们需要更少的代码来处理异常情况(当然,除非有业务需求来进行区分)。
是的,@JeroenMostert 是对的,?? new List<InterestedParty>()
在很多情况下更合适
@JeroenMostert 你介意添加一个答案吗?我想批准你的答案是正确的。
或者更好的是,返回IEnumerable<InterestedParty>
并使用?? Enumerable.Empty<InterestedParty>()
,因为这不会创建新的列表并被缓存。【参考方案2】:
在 .csproj 中的 .NET 6 中,您可以设置可为空的 disable
:
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
</PropertyGroup>
【讨论】:
以上是关于C# 9+ 中的 HttpClient 空警告的主要内容,如果未能解决你的问题,请参考以下文章