如何将“任何不可为空的类型”指定为泛型类型参数约束?

Posted

技术标签:

【中文标题】如何将“任何不可为空的类型”指定为泛型类型参数约束?【英文标题】:How do I specify "any non-nullable type" as a generic type parameter constraint? 【发布时间】:2019-12-11 14:39:58 【问题描述】:

这篇文章是针对 C# 8 的。假设我想要这个方法:

public static TValue Get<TKey, TValue>(
  this Dictionary<TKey, TValue> src, 
  TKey key, 
  TValue @default
) 
=> src.TryGetValue(key, out var value) ? value : @default;

如果我的.csproj 看起来像这样(即启用了 C# 8 和可空类型,则所有警告都是错误):

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <LangVersion>8</LangVersion>
    <Nullable>enable</Nullable>
    <WarningsAsErrors>true</WarningsAsErrors>
  </PropertyGroup>
  …
</Project>

此代码将产生以下构建时错误:

DictionaryEx.cs(28, 78): [CS8714] 类型“TKey”不能用作泛型类型或方法“Dictionary”中的类型参数“TKey”。类型参数“TKey”的可空性与“notnull”约束不匹配。

有没有办法指定TKey 必须是不可为空的类型?

【问题讨论】:

对我来说,这段代码编译时没有 CS8714 或任何其他警告。 【参考方案1】:

好的,刚刚发现可以使用notnull约束:

public static TValue Get<TKey, TValue>(
    this Dictionary<TKey, TValue> src, 
    TKey key, TValue @default)
    where TKey : notnull
    => src.TryGetValue(key, out var value) ? value : @default;

【讨论】:

这在 VS 16.2.3 中给出了一个 IntelliSense 错误“无法解析符号”,但它确实编译和工作。 我找不到这方面的任何文档。我们知道这是否是面向未来的吗? @NetherGranite:至少一年后,这现在被记录为 Microsoft 在语言参考中的 Generic Type Constraint 文档以及编程指南中的 Constraints on Type Parameters 的一部分。

以上是关于如何将“任何不可为空的类型”指定为泛型类型参数约束?的主要内容,如果未能解决你的问题,请参考以下文章

编写高质量代码改善C#程序的157个建议——建议45:为泛型类型参数指定逆变

C#如何将类型Type作为泛型T的参数T传递

无法将类型“Int”的值转换为泛型中的预期参数类型“Int”

C# 泛型方法约束为继承自某类时,调用方法,传子类实参,为什么报错?应该怎么写

泛型方法多 (OR) 类型约束

将返回值转换为泛型类型