为什么 Visual Studio 在将 KeyValuePair 枚举传递给 FormUrlEncodedContent 构造函数时生成警告 CS620?
Why does Visual Studio generate warning CS620 when passing KeyValuePair enumeration to FormUrlEncodedContent constructor?
考虑以下代码:
using System;
using System.Collections.Generic;
using System.Net.Http;
namespace dla.test2{
internal class Test{
public static void Main(){
var map=new Dictionary<string,string>(){
["hello"]="world"
};
using var foo=new FormUrlEncodedContent(map);
}
}
}
调用 FormUrlEncodedContent
的构造函数会在构建时产生以下编译器警告:
Warning
CS8620 Argument of type 'Dictionary<string, string>' cannot be used
for parameter 'nameValueCollection' of type
'IEnumerable<KeyValuePair<string?, string?>>' in
'FormUrlEncodedContent.FormUrlEncodedContent(IEnumerable<KeyValuePair<string?,
string?>> nameValueCollection)' due to differences in the nullability
of reference types.
documentation for FormUrlEncodedContent 表示构造函数应该接受 IEnumerable<KeyValuePair<string,string>>?
。我的 map
变量是一个 Dictionary<string,string>
,大概会实现接口 IEnumerable<KeyValuePair<string,string>>
,所以我希望这里没有问题。 为什么会出现警告?
我正在使用 Visual Studio 16.8.0 目标 NETCore5。
我觉得这里实际上有几个问题:
- 为什么文档有误?而且,
- 为什么发出警告。
后者更容易回答。前者,没那么多(你得问微软)。
我还没有安装 .NET 5。但我可以使用以下代码在 .NET Core 3.1 中重现完全相同的警告:
static void Main(string[] args)
{
var map = new Dictionary<string, string>()
{
["hello"] = "world"
};
M1(map);
}
static void M1(IEnumerable<KeyValuePair<string?, string?>>? nameValueCollection) { }
可以从您 copy/pasted 的警告中推断出您的问题 actual .NET 5 版本的声明 FormUrlEncodedContent
class 构造函数必须是,所以我只是写了一个不需要安装 .NET 5 的例子。
事实上,如果我们查看 the source code,我们可以看到该构造函数的实际声明:
public FormUrlEncodedContent(IEnumerable<KeyValuePair<string?, string?>> nameValueCollection)
这告诉我文档不准确,如果不是完全错误的话。我没有关注支持可空引用类型的框架的变化,所以我不确定文档是否应该为这种情况显示可空类型参数。在我看来应该,但显然不是。至少,令我惊讶的是文档将 nameValueCollection
参数本身显示为可为空(实际上它不是),不要介意它将 KeyValuePair<TKey, TValue>
类型参数显示为 non-nullable ,而实际上它们可以为空。
但是无论如何,通过了解 .NET 5 中的 actual 方法签名是什么,我们可以说警告存在只是因为确实,您的调用涉及传递类型这与类型参数的可空性不一致。
为什么这会产生警告?好吧……虽然我们知道在这种情况下没有代码会写入可枚举值中的可为空值,但没有 compile-time 保证 。由于您的对象正在返回值是 non-nullable 引用的对象,并且您将其传递给声明为接受可为 null 的值的方法,这意味着理论上该方法可以 modify 通过将这些可为空的值设置为 null
,这违反了您自己的代码假设这些值为 non-nullable.
考虑以下代码:
using System;
using System.Collections.Generic;
using System.Net.Http;
namespace dla.test2{
internal class Test{
public static void Main(){
var map=new Dictionary<string,string>(){
["hello"]="world"
};
using var foo=new FormUrlEncodedContent(map);
}
}
}
调用 FormUrlEncodedContent
的构造函数会在构建时产生以下编译器警告:
Warning CS8620 Argument of type 'Dictionary<string, string>' cannot be used for parameter 'nameValueCollection' of type 'IEnumerable<KeyValuePair<string?, string?>>' in 'FormUrlEncodedContent.FormUrlEncodedContent(IEnumerable<KeyValuePair<string?, string?>> nameValueCollection)' due to differences in the nullability of reference types.
documentation for FormUrlEncodedContent 表示构造函数应该接受 IEnumerable<KeyValuePair<string,string>>?
。我的 map
变量是一个 Dictionary<string,string>
,大概会实现接口 IEnumerable<KeyValuePair<string,string>>
,所以我希望这里没有问题。 为什么会出现警告?
我正在使用 Visual Studio 16.8.0 目标 NETCore5。
我觉得这里实际上有几个问题:
- 为什么文档有误?而且,
- 为什么发出警告。
后者更容易回答。前者,没那么多(你得问微软)。
我还没有安装 .NET 5。但我可以使用以下代码在 .NET Core 3.1 中重现完全相同的警告:
static void Main(string[] args)
{
var map = new Dictionary<string, string>()
{
["hello"] = "world"
};
M1(map);
}
static void M1(IEnumerable<KeyValuePair<string?, string?>>? nameValueCollection) { }
可以从您 copy/pasted 的警告中推断出您的问题 actual .NET 5 版本的声明 FormUrlEncodedContent
class 构造函数必须是,所以我只是写了一个不需要安装 .NET 5 的例子。
事实上,如果我们查看 the source code,我们可以看到该构造函数的实际声明:
public FormUrlEncodedContent(IEnumerable<KeyValuePair<string?, string?>> nameValueCollection)
这告诉我文档不准确,如果不是完全错误的话。我没有关注支持可空引用类型的框架的变化,所以我不确定文档是否应该为这种情况显示可空类型参数。在我看来应该,但显然不是。至少,令我惊讶的是文档将 nameValueCollection
参数本身显示为可为空(实际上它不是),不要介意它将 KeyValuePair<TKey, TValue>
类型参数显示为 non-nullable ,而实际上它们可以为空。
但是无论如何,通过了解 .NET 5 中的 actual 方法签名是什么,我们可以说警告存在只是因为确实,您的调用涉及传递类型这与类型参数的可空性不一致。
为什么这会产生警告?好吧……虽然我们知道在这种情况下没有代码会写入可枚举值中的可为空值,但没有 compile-time 保证 。由于您的对象正在返回值是 non-nullable 引用的对象,并且您将其传递给声明为接受可为 null 的值的方法,这意味着理论上该方法可以 modify 通过将这些可为空的值设置为 null
,这违反了您自己的代码假设这些值为 non-nullable.