关于c#:两个方法参数之间的泛型类型参数中的可空性不匹配 | 珊瑚贝

Nullability mismatch in generic type parameter between two method arguments


我编写了以下扩展方法:

1
2
3
4
5
// using System.Collections.Generic;

internal static class TExtensions {
    internal static bool In< T >(this T val, HashSet< T > hs) => hs.Contains(val);
}

并尝试按如下方式使用它:

1
2
3
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.

因为编译器将 T 类型参数解析为 s 或 string? 的类型;但散列集不是 HashSet<T>,它是可空 string (HashSet<string?>) 的散列集,而是不可空 string (HashSet<string>) 的散列集。

我可以通过package一个空检查来解决这个问题:

1
2
3
if (s is { }) {
    var result = s.In(hs);
}

或将哈希集显式键入为具有可为空的元素:

1
var hs = new HashSet<string?>();

但是有什么方法可以使用可为空的属性来允许这种情况吗?或者还有什么我可以在 In 扩展方法中改变的吗?

  • 我会说警告正在发挥作用——请注意 hs.Contains(s) 有同样的问题。虽然这通过扩展方法的魔力”起作用”,但您不希望鼓励在 null 值上调用方法。充其量它看起来像一个错误,最坏的情况是它隐藏了一个实际的错误。当您确定它是有意的时,我会将它写为 s!.In(hs),它会在不检查的情况下抑制警告。 (另外,在通过泛型为每种类型添加扩展方法时要非常小心——至少考虑让你的类 internal 这样你的添加不会渗透到其他人的程序集中。)


In方法的第一个参数可以使用[AllowNull]属性:

1
internal static bool In< T >([AllowNull] this T val, HashSet< T > hs) => hs.Contains(val);

但是,正如您在问题中描述的那样,这里的实际问题是推断的泛型类型参数由 s In 方法将被称为 In<string?>,它要求哈希集为 HashSet<string?>。您必须告诉编译器使用 string 而不是 string?:s.In<string>(hs).

如果你可以约束到不可为空的引用类型,你可以使用这个:

1
internal static bool In< T >(this T? val, HashSet< T > hs) where T : class => val != null && hs.Contains(val);

对于值类型,实现将是:

1
internal static bool In< T >(this T? val, HashSet< T > hs) where T : struct => val.HasValue && hs.Contains(val.Value);

请注意,如果类型参数本身可以为空,则只有第一个版本(带有 [AllowNull] 属性)有效。


您当然可以使用 null-forgiving-operator 来关闭编译器,而不是更改扩展方法:s.In(hs!) 或 s!.In(hs).


来源:https://www.codenong.com/58846244/

微信公众号
手机浏览(小程序)

Warning: get_headers(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(): Failed to enable crypto in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(https://static.shanhubei.com/qrcode/qrcode_viewid_9494.jpg): failed to open stream: operation failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57
0
分享到:
没有账号? 忘记密码?