C#:通用 T 的默认值?不为空;行为随着通用约束而改变

2023-12-31

我有一个泛型类,应该对(不可为空)引用和值类型(参数、返回...)进行操作,但内部需要可以为空的字段。

using System;

public class Gen<T> // where T : struct
{
    public class Data
    {
        public T? t;
    }

    public static void Write(string s)
    {
        Data d = new Data();
        Console.WriteLine("Default of {0} is {1}", s, d.t == null ? "null" : "NOT null");
    }

    // ... other stuff that uses T and not T? like
    // public T DoSomething(T value) ...
}

static class Program
{
    static void Main(string[] args)
    {
        Gen<int>.Write("int?");
        Gen<string>.Write("string?");
    }
}

在启用可为 null 的情况下编译 (.NET 5) 时,此代码不会产生任何错误或警告。 然而,行为并不符合我的预期。

Default of int? is NOT null
Default of string? is null

在寻找解决方案时,我发现当where T : struct添加约束(并删除 Gen.Write()),行为更改为

Default of int? is null

奇怪的是,约束改变了行为。

有人知道编写这样一个通用类的优雅解决方案吗? 使用也支持引用类型的自定义 Nullable 类或为每个 T 使用单独的 bool 标志?归档有点乏味。


如果你想使用Nullable<int>你不应该使用int,所以使用:

Gen<int?>.Write("int?");

那么输出将是

Default of int? is null
Default of string? is null

问题中的代码是一个示例。真正的类没有Write方法并且从不使用该类型的字符串。然而正如我 由“其他内容”表示,它使用 T 以及 T?。所以它不是 想要实例化它int?代替int.

首先我想解释一下为什么这并不奇怪struct泛型类中的约束会改变行为。因为实际上,如果您是 T? means Nullable<T>,所以如果你使用Gen<int>.Write("int?")t将是一个Nullable<int>。但是之后Gen<string>.Write("string")根本不会编译string不是一个struct。所以它与约束有着完全不同的含义。

启用 C#8 后,您可以删除struct受约束,那么t仍然是intstring将是一个可为空的string。所以问号的含义是:对于引用类型,它是可为空的引用类型,否则它就是这样。

您不能同时拥有可以为 null 的引用类型的泛型类型或可以为 null 的值类型而不使用所需的泛型类型,因此请使用int?如果它必须可为空。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#:通用 T 的默认值?不为空;行为随着通用约束而改变 的相关文章

随机推荐

  • 增量列是否会使该列上的 B 树索引不平衡?

    我一直在思考两个问题 在互联网上找不到任何关于此的资源 dbms 是如何处理的 或者他们呢 尤其是甲骨文 在提问之前 这里有一个例子 假设我有一个主表 MASTER 和从表 SLAVE 主表有一个 ID 列 它是主键 索引由Oracle创建
  • 查找该月的第一个星期二

    我正在尝试编写一个函数 它将日期向量作为输入并返回日期向量 其中输出是与输入日期匹配的该月第一个星期二的日期 So 2012 11 19 gt 2012 11 06 etc 我在一次约会中取得了一些成功 但无法推广到矢量情况 有人可以帮忙吗
  • 如何在mysql中提取两个特殊字符之间的字符串

    我正在使用查询从数据库中提取特殊字符之间的数字 select number from database where number between like 如何编写MySQL脚本来获取101 out of lt 101 gt Use SUB
  • 在 Cocoa/Objective-C 中创建看门狗的原因和方法

    祝大家星期一快乐 这是我的情况 非常感谢任何帮助 我创建了一个可执行文件 安装后将其放置在计算机的 Launch Agents 文件夹中 理论上它应该永久运行 每秒收集数据 它可以在机器睡眠时停止 但在计算机重新激活时重新启动 这是我的问题
  • asp.net MVC3 上的自定义错误页面

    我正在开发一个 MVC3 基础网站 我正在寻找一种解决方案来处理错误并为每种错误渲染自定义视图 因此 想象一下我有一个 错误 控制器 其主要操作是 索引 通用错误页面 并且该控制器将对用户可能出现的错误有更多操作 例如 Handle500
  • 模板函数的前向声明

    我有一个带有朋友模板函数的模板类 我目前有以下代码并且它正在工作 template
  • 空的“()”在 Matlab 矩阵上有什么作用?

    In Matlab 表达式到底是什么M 在哪里做M是一个矩阵 gt gt M magic 3 gt gt M ans 8 1 6 3 5 7 4 9 2 是表达式isequaln M M 在所有情况下都是如此吗 是M 只是一个副本M 或相同
  • 如何将对象转换为数组?

    输出以下内容 Array 0 gt Object fields private gt Array id gt 9093 name gt zahir Object
  • 如何上传 pdf 文件?

    我必须使用以下方式在网络应用程序中上传 pdf 文件FileUpload控制 我已经尝试过这段代码 但它有一些问题 谁能帮我这个 protected void Button1 Click object sender EventArgs e
  • 如何更改 UINavigationBar 及其上按钮的颜色?

    我想改变 UINavigationBar 的颜色 是否可以保留不同颜色的 UINavigationBar 和按钮 UINavigationBar 有一个tintColor为此的财产
  • 是否可以创建一个可以在 blobstore 中上传照片的 Google 应用引擎端点?

    我想知道是否可以使用端点在应用程序引擎 blobstore 中上传照片 如果是 请说明如何或重定向到任何可用资源 如果没有 您能否公开任何简单的替代方案 使用另一个库 将标准 servlet 与其他库一起使用 这篇文章应该有用 通过应用程序
  • 与 CMPSB 指令混淆

    我一直在看这段代码 我对代表 cmpsb line LOOP push cx mov cx 0x000B eleven character name mov si ImageName image name to find push di r
  • PHP 5 秒倒计时(CLI,而非 JavaScript)

    我正在编写一个 PHP CLI 命令行 脚本 如果意外运行 它将造成一些不可逆转的损害 我想在继续执行脚本之前显示 5 秒倒计时器 我怎样才能用 PHP 做到这一点 不要倒计时 假设有人实际上正在观看屏幕并阅读 理解倒计时的含义 完全有可能
  • 单击或按 Enter 键时触发主干事件

    I am new to backbone and I am looking for a way for my button to be triggered when I press Enter as well as clicking Cur
  • 在分区内的多个列上进行 Spark 聚合,无需进行洗牌

    我正在尝试在多个列上聚合数据框 我知道聚合所需的所有内容都在分区内 也就是说 不需要洗牌 因为聚合的所有数据都是分区本地的 采取example http dmtolpeko com 2015 02 12 multi column key a
  • 高级 (?) AND / OR 查询

    对于相当简单的表结构 即 人员 标准和人员标准 组合表 我目前设置了一个查询 选择具有所有选定条件的所有人员 查询本身现在看起来像这样 SELECT p PersonID FROM Person p SELECT DISTINCT Pers
  • 使用开源软件的可填写、可保存表单的 PDF [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我的问题是一个延伸this one https stackoverflow com questions
  • 如何在clickhouse中添加列

    我在 clickhouse 中有一个表 称为 my table 其中有重复项 my table rep1 我需要添加一个 float64 类型的列 默认值 1 我该怎么做呢 我希望默认值实际上不会添加到现有条目中 The 文档 https
  • Spring Boot Hibernate中的H2 DB不生成Db Schema

    我希望我的 Spring 应用程序自动生成数据库架构和表 我已经阅读了有关该主题的一些问答 并将数据库 URL 设置为 H2DataSource setUrl jdbc h2 mem tmp db INIT 创建架构 如果不是 存在 GPS
  • C#:通用 T 的默认值?不为空;行为随着通用约束而改变

    我有一个泛型类 应该对 不可为空 引用和值类型 参数 返回 进行操作 但内部需要可以为空的字段 using System public class Gen