关于c#:两个方法参数之间的泛型类型参数中的可空性不匹配
Nullability mismatch in generic type parameter between two method arguments
我编写了以下扩展方法:
|
// using System.Collections.Generic;
internal static class TExtensions { |
并尝试按如下方式使用它:
|
var s = DateTime.Now.Hour < 15 ?"abcd" : null;
var hs = new HashSet<string>(); Console.WriteLine(s.In(hs)); |
编译器在最后一行给我一个警告:
CS8620 Argument of type 'HashSet' cannot be used for parameter 'hs' of type 'HashSet' in 'bool TExtensions.In(string? val, HashSet? hs)' due to differences in the nullability of reference types.
因为编译器将
我可以通过package一个空检查来解决这个问题:
|
if (s is { }) {
var result = s.In(hs); } |
或将哈希集显式键入为具有可为空的元素:
|
var hs = new HashSet<string?>();
|
但是有什么方法可以使用可为空的属性来允许这种情况吗?或者还有什么我可以在
相关讨论
- 我会说警告正在发挥作用——请注意
hs.Contains(s) 有同样的问题。虽然这通过扩展方法的魔力"起作用",但您不希望鼓励在null 值上调用方法。充其量它看起来像一个错误,最坏的情况是它隐藏了一个实际的错误。当您确定它是有意的时,我会将它写为s!.In(hs) ,它会在不检查的情况下抑制警告。 (另外,在通过泛型为每种类型添加扩展方法时要非常小心——至少考虑让你的类internal 这样你的添加不会渗透到其他人的程序集中。)
|
internal static bool In< T >([AllowNull] this T val, HashSet< T > hs) => hs.Contains(val);
|
但是,正如您在问题中描述的那样,这里的实际问题是推断的泛型类型参数由
如果你可以约束到不可为空的引用类型,你可以使用这个:
|
internal static bool In< T >(this T? val, HashSet< T > hs) where T : class => val != null && hs.Contains(val);
|
对于值类型,实现将是:
|
internal static bool In< T >(this T? val, HashSet< T > hs) where T : struct => val.HasValue && hs.Contains(val.Value);
|
请注意,如果类型参数本身可以为空,则只有第一个版本(带有
您当然可以使用 null-forgiving-operator 来关闭编译器,而不是更改扩展方法: