深度解读C# 11 的 Required 成员:编译期状态验证强化

(入门向)在Ubuntu22.04.3安装Matlab2021b,以及无法安装在当前目录下的解决办法(见最后) 还有这个/usr/local是只读状态,我试过sudo chmod..去改那个文件的读,结果还是安装不了,我不是这个默认路径,因为它文件夹还是只读,于是我在matlab2021b下创了一个bin,并选上。输入完成后,依次按y,因为里面有三个文件,他会让你确定3次密码,直接yyy跳过即可。你可能会遇到装不下的情况,这个软件占30g,可是你分配给虚拟机就剩10g。,于是我去Downloads下建了一个matlab2021b文件夹,果然好使,3).此时,会提示你输入密码,因为这个rar是有密码的, 阅读详情

深度解读C# 11 的 Required 成员:编译期状态验证强化

在 C# 编程中,确保对象状态的正确性是保证程序健壮性的关键。C# 11 引入的 Required 成员特性,为开发者提供了一种在编译期对对象成员进行状态验证的强大手段,能有效避免因未初始化成员而导致的运行时错误。深入了解 Required 成员,有助于编写更加严谨和可靠的代码。

一、技术背景

在传统的 C# 编程中,对象成员的初始化依赖于开发者的良好习惯和约定。这意味着对象在创建时,某些重要成员可能未被初始化,从而在运行时引发空引用异常或其他逻辑错误。虽然可以通过构造函数或属性设置器来进行初始化检查,但这种方式在大型代码库中可能变得繁琐且容易出错。C# 11 的 Required 成员特性则将这种验证提前到编译期,让编译器帮忙检查对象状态,显著提高代码的稳定性。

二、核心原理

Required 成员特性基于编译器的静态分析。当一个类型的成员被标记为 Required 时,编译器会在编译过程中检查该类型的对象在使用前,所有 Required 成员是否都已初始化。如果发现未初始化的 Required 成员,编译器会生成错误,阻止程序编译通过。这种机制通过对代码的静态分析,无需在运行时进行额外的检查,提高了程序的可靠性和性能。

三、底层实现剖析

从编译器角度来看,当解析到带有 Required 特性的成员声明时,编译器会在符号表中为该成员标记一个特殊的标志,表示其为必需成员。在编译对象创建和使用的代码时,编译器会检查对象实例化过程中对这些必需成员的赋值情况。如果没有检测到赋值操作,编译器会依据符号表中的标记生成相应的编译错误。例如,在 Roslyn 编译器中,相关的语法分析和语义分析阶段会处理 Required 特性,对未初始化的必需成员进行错误报告。

四、代码示例

基础用法

using System;

class Person
{
    // 标记为Required成员
    [System.ComponentModel.DataAnnotations.Required]
    public string Name { get; set; } = null!;

    [System.ComponentModel.DataAnnotations.Required]
    public int Age { get; set; }
}

class Program
{
    static void Main()
    {
        // 正确初始化
        Person person1 = new Person
        {
            Name = "Alice",
            Age = 30
        };
        Console.WriteLine($"Name: {person1.Name}, Age: {person1.Age}");

        // 错误示例:未初始化Name成员
        // Person person2 = new Person { Age = 25 }; 
        // 上述代码会导致编译错误:CS8618: 非可空属性“Name”在退出构造函数时必须包含非空值。请考虑将该属性声明为可以为 null。
    }
}

功能说明:定义一个 Person 类,其中 Name 和 Age 成员被标记为 Required。在 Main 方法中,演示正确初始化对象和未初始化必需成员导致编译错误的情况。
关键注释:[System.ComponentModel.DataAnnotations.Required] 标记成员为必需,null! 用于告知编译器该属性实际上不会为 null,即使默认值为 null。
运行结果:正确初始化对象时,输出 Name: Alice, Age: 30。若尝试未初始化 Name 成员创建对象,编译器报错,程序无法运行。

进阶场景

using System;
using System.Collections.Generic;

class Order
{
    [System.ComponentModel.DataAnnotations.Required]
    public string OrderId { get; set; } = null!;

    [System.ComponentModel.DataAnnotations.Required]
    public List<string> Items { get; set; } = null!;

    public void PrintOrderDetails()
    {
        Console.WriteLine($"Order ID: {OrderId}");
        Console.WriteLine("Items:");
        foreach (var item in Items)
        {
            Console.WriteLine(item);
        }
    }
}

class Program
{
    static void Main()
    {
        // 初始化包含复杂类型的Required成员
        Order order = new Order
        {
            OrderId = "12345",
            Items = new List<string> { "Item1", "Item2" }
        };
        order.PrintOrderDetails();

        // 错误示例:未初始化Items成员
        // Order badOrder = new Order { OrderId = "67890" }; 
        // 上述代码会导致编译错误:CS8618: 非可空属性“Items”在退出构造函数时必须包含非空值。请考虑将该属性声明为可以为 null。
    }
}

功能说明:定义一个 Order 类,包含 OrderId 和 Items 两个 Required 成员,其中 Items 是一个复杂类型 List<string>。在 Main 方法中,展示正确初始化对象以及未初始化复杂类型必需成员导致编译错误的情况,并通过 PrintOrderDetails 方法打印订单信息。
关键注释:同样使用 [System.ComponentModel.DataAnnotations.Required] 标记必需成员,正确初始化复杂类型 Items 确保程序正常运行。
运行结果:正确初始化对象时,输出订单 ID 和商品列表。若未初始化 Items 成员,编译器报错,程序无法运行。

避坑案例

错误案例:在继承中忽略Required成员初始化

using System;

class BaseClass
{
    [System.ComponentModel.DataAnnotations.Required]
    public string BaseProperty { get; set; } = null!;
}

class DerivedClass : BaseClass
{
    // 错误:未初始化BaseProperty
    public DerivedClass()
    {
        // 未对BaseProperty进行初始化
    }
}

class Program
{
    static void Main()
    {
        // DerivedClass derived = new DerivedClass(); 
        // 上述代码会导致编译错误:CS8618: 非可空属性“BaseProperty”在退出构造函数时必须包含非空值。请考虑将该属性声明为可以为 null。
    }
}

功能说明:定义一个基类 BaseClass 包含 Required 成员 BaseProperty,派生类 DerivedClass 的构造函数未初始化从基类继承的 BaseProperty。在 Main 方法中尝试创建派生类对象会导致编译错误。
关键注释:在继承体系中,派生类构造函数需要确保初始化从基类继承的 Required 成员。
运行结果:尝试创建 DerivedClass 对象时,编译器报错,程序无法运行。

修复方案

using System;

class BaseClass
{
    [System.ComponentModel.DataAnnotations.Required]
    public string BaseProperty { get; set; } = null!;
}

class DerivedClass : BaseClass
{
    public DerivedClass()
    {
        BaseProperty = "Initialized Value";
    }
}

class Program
{
    static void Main()
    {
        DerivedClass derived = new DerivedClass();
        Console.WriteLine($"Base Property Value: {derived.BaseProperty}");
    }
}

功能说明:在派生类 DerivedClass 的构造函数中初始化从基类继承的 BaseProperty。在 Main 方法中成功创建派生类对象并输出 BaseProperty 的值。
关键注释:在派生类构造函数中为 BaseProperty 赋值,避免编译错误。
运行结果:输出 Base Property Value: Initialized Value。

五、实践建议

  • 明确状态契约:使用 Required 成员明确类型的状态契约,让代码阅读者和维护者清楚了解对象创建时必须满足的条件。
  • 结合其他验证机制:虽然 Required 成员在编译期提供了强大的验证,但在运行时仍可能需要其他验证机制,如输入验证等,以确保程序的全面正确性。
  • 注意继承关系:在继承体系中,派生类要确保正确初始化从基类继承的 Required 成员,避免编译错误。

六、常见问题解答

  1. Required 成员与可空引用类型有什么关系?
    Required 成员通常与可空引用类型一起使用。可空引用类型允许开发者明确标记哪些变量可以为 null,而 Required 成员则进一步保证在对象创建时某些成员不能为 null。例如,将一个引用类型成员标记为 Required 且使用可空引用类型语法,可以在编译期防止未初始化的 null 引用。
  2. 可以在接口中使用 Required 成员吗?
    不可以,Required 特性目前只能用于类和结构体的成员。接口主要定义行为契约,而 Required 成员更侧重于对象状态的验证,所以在接口中使用没有意义。
  3. Required 成员在不同的.NET 版本中有兼容性问题吗?
    Required 成员是 C# 11 的新特性,仅在支持 C# 11 的.NET 版本(如.NET 7 及更高版本)中可用。如果项目使用较低版本的.NET 或 C#,则无法使用该特性,需要考虑升级或者采用其他方式进行对象状态验证。

C# 11 的 Required 成员特性为编译期状态验证带来了显著的提升,通过在编译阶段强制检查对象成员的初始化状态,有效减少了运行时错误的发生。开发者在使用该特性时,需注意其适用场景和继承体系中的初始化问题,并结合其他验证机制确保程序的全面正确性。随着 C# 语言的不断发展,这类编译期验证特性有望进一步完善,为开发者提供更强大的工具来编写高质量的代码。

optee技术简介 OP-TEE(Open Portable Trusted Execution Environment)是一种开源的可信执行环境(TEE),专为ARM TrustZone架构设计。TEE是一种独立的执行环境,运行在主操作系统之外,为敏感任务提供安全的计算空间,如加密、身份验证、密钥管理等。 阅读详情

相关推荐

海康视觉相机驱动软件MVS参数配置全攻略(附接线图+避坑指南)

本文提供了海康视觉相机驱动软件MVS从硬件连接到软件参数配置的完整指南。详细解析了供电与通讯线缆的区分、PNP/NPN信号逻辑的接线避坑方法,并重点阐述了MVS软件中触发模式、网络IP配置、图像采集及光源控制等核心参数的设置技巧,旨在帮助用户快速完成相机调试,实现稳定高效的图像采集。

weixin_29204205的博客 399

C#的required关键字

required。

csycyl的博客 1816

汇川伺服驱动器参数优化实战指南

本文详细介绍了汇川伺服驱动器参数优化的实战技巧,涵盖控制模式选择、电子齿轮比调整、刚性匹配与振动抑制等关键内容。通过实际案例和实用技巧,帮助工程师快速掌握伺服驱动器参数调校方法,提升设备运行精度和稳定性。特别针对高精度定位和高速响应场景提供了专业指导。

weixin_29070721的博客 735

C# 11 中的 required members

C# 11 中的 required membersIntro在 C# 11 中引入了一个新的特性 —— Required Members,引入了一个新的 required 关键词,可以用来表示字段或者属性在类型初始化的时候必须要进行初始化,这一特性也进一步的改进了可空引用类型的用法。Sample示例如下:privaterecordPerson { publicrequiredstr...

dotNET跨平台 1587

Android Studio连接手机详细教程(包含遇到的问题集)

如果以上内容全都调试正确了,还是存在这个无法安装的问题,多半是一开始用的别的手机进行调试安装,然后抽掉线重新换上另一个手机安装调试才会报错。无法识别的 USB 设备,跟这台计算机连接的前一个 USB 设备工作不正常,Windows 无法识别它。此时,我的开发者选项已经开启,并且windows系统和android studio已经能够识别我的设备了,但还是报了这样的错误。右击你的手机——>更新驱动程序——>浏览我的计算机以查找驱动程序软件。右击此电脑——>属性——>设备管理器——>便携设备。

IT小郭的技术博客 4万+

5G核心网Framed Routing功能解析:基于PFCP的帧路由机制与多终端互联实践

5G核心网Framed Routing功能解析:基于PFCP的帧路由机制与多终端互联实践

大家好,我是码农老gou,一名专注于编程技术的程序员。在这个博客中,我将与大家分享我在工作和学习中的经验、见解以及一些实用的技术干货。 1467

require使用

1.   Require是什么? 1)        当我们在一个页面中引入很多个js的时候,http请求就增多,浏览器会停止渲染,失去响应的时间会增长 2)        因为要根据各js之间的依赖来进行引入,因此必须严格保证加载顺序,依赖性最大的模块一定要放到最后加载有时候依赖过于复杂,引入容易出现问题; 引入require.js就是来解决这两个问题的

qq_36592414的博客 910

PyInstaller打包后在Win7无法运行,提示缺少`api-ms-win-core-path-l1-1-0.dll`问题解决

这个问题的关键在于Python 3.12和Windows 7之间的兼容性问题。解决方法是使用Python 3.8.8版本进行打包,确保程序能够在Windows 7系统上运行。如果你也遇到类似的问题,不妨尝试降级Python版本,看看是否能够解决。希望我的经验能够帮到你!如果你在使用PyInstaller打包时遇到其他问题,欢迎留言讨论。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 994

关于required 修饰符

有时候偶尔看到这个修饰符 一直没注意去看  不想 今天看到  王巍  的swift书 就随便记一下  以备以后查看 下面是一段示例代码 class MyClass {    var str:String   required init(str:String) {        self.str = str    }        required init(strrr: Int){

韩万杰的博客 1180

【笔记篇】Davinci Configurator OS模块(下)

AUTOSAR OS的配置项和Vevtor MICROSAR OS的特性

weixin_47571898的博客 1157

学Simulink——基于Simulink的固态变压器(SST)多级协同控制​

本文介绍了基于Simulink的固态变压器(SST)多级协同控制系统设计与仿真方法。SST作为智能电网关键设备,包含AC-DC整流、DC-DC隔离和DC-AC逆变三级变换器。针对级间耦合问题,提出了能量-功率协同控制策略,通过纵向解耦和横向联动实现稳定运行。详细演示了在Simulink中搭建三级主电路、设计协同控制器(含电网定向控制、功率前馈和虚拟惯性控制)的全过程,并通过负载突变测试验证了系统动态性能(直流母线电压波动<2%)。最后给出了工程部署建议,包括数字控制延时补偿、启动序列设计和代码自动生成

xiaoheshang_123的博客 206

深度解析C# 11的Required成员:编译期验证保障数据完整性

C# 11引入的Required成员特性,允许开发者在类或结构体中标记成员为required,确保对象在初始化时这些成员被赋值,避免运行时因未初始化成员导致的错误,极大增强了代码健壮性与数据完整性。

dotnethello的博客 2134

1.2 amdgpu_bo的设计分析 — gem层和ttm层

本文分析了AMD KFD的BO设计架构,重点介绍了DRM子系统中缓冲对象的多层继承关系。文章首先展示了核心继承层次图,包括DRM通用层(drm_gem_object)、TTM内存管理层(ttm_buffer_object)、AMD驱动层(amdgpu_bo)和KFD计算层(kgd_mem)。随后详细解析了drm_gem_object结构体的关键功能,包括用户空间接口管理、内存映射支持、引用计数机制以及DMA-BUF导入/导出功能。

图形/计算GPU的驱动与虚拟化技术分享园地 2548

C# 中值类型[Required(*****)] 报错

转载于:https://www.cnblogs.com/sakuya-GD/p/4979868.html

weixin_30666943的博客 2562

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

RequireComponent的使用

RequireComponent的使用:     当你添加的一个用了RequireComponent组件的脚本,需要的组件将会自动被添加到game object(游戏物体)。这个可以有效的避免组装错误。举个例子一个脚本可能需要刚体总是被添加在相同的game object(游戏物体)上。用RequireComponent属性的话,这个过程将被自动完成,因此你可以永远不会犯组装错误。

taotaoahui 1万+

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Lua与C#连接

        C#连Lua学了一天,先记录下,方便之后自己去别的电脑上安装。以及几个bug一:搭建lua环境,这里直接提供个Lua for windows ,解压就能用。二:vs2017引入两个dll(luanet.dll,luaInterface.dll),并添加引用(luaInterface.dll)https://pan.baidu.com/s/1-NTm0d0pjfrnvyshKIKf5...

GameRoad 544

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

C语言REQUIRE函数,模块化编程--require使用

AMD--requireAMD规范:异步模块加载机制服务器端 -- 同步加载 浏览器端 -- 异步加载 --> 因为在服务器端中,所有模块都存放在硬盘中,等待时间就是硬盘读取时间,但是浏览器端,所有模块都存放在服务器上,等待时间取决于网速快慢,可能很长时间浏览器处于假死状态1.下载require.js,确定index.js为程序入口,则 --> data-ma...

weixin_34917128的博客 502

浅谈require和import

最近在学习webpack时候,教程上用到的是require,但是之前我写代码用的Import比较多,所以借这个机会来学习一下: node编程中最重要的思想就是模块化,import和require都是被模块化所使用。 遵循规范 –require 是 AMD规范引入方式 –import是es6的一个语法标准,如果要兼容浏览器的话必须转化成es5的语法 调用时间 –require是运行时调用,所以req...

归小超博客 3万+

.net C#代码契约Contract.Require Contract.Equal等为什么不生效?

C#中为什么代码契约不生效?很令人迷惑。 1. 表现令人迷惑 如下图1,第23行仿佛就不存在似的。 2. 为什么呢 追踪一下Require的源码,能看到下图所示 3. 宏定义 在文件中定义变量,则生效。 4. 为证明,上个结果图 附,如下链接,可能有点用。 https://docs.microsoft.com/en-us/dotnet/framework/debug-trace-profile/code-contracts ...

festone000的专栏 922

RequireComponent的使用(转自taotaoahui)

 当你添加的一个用了RequireComponent组件的脚本,需要的组件将会自动被添加到game object(游戏物体)。这个可以有效的避免组装错误。举个例子一个脚本可能需要刚体总是被添加在相同的game object(游戏物体)上。用RequireComponent属性的话,这个过程将被自动完成,因此你可以永远不会犯组装错误。   用法:在新建的类前面加 [RequireComponent(...

Uqiumu的博客 572

第6章第4节:自定义分词器

本节详解Elasticsearch自定义分词器,解析analyzer三段式结构(char_filter→tokenizer→filter),掌握常用组件如ik_max_word、synonym_graph、ngram等。通过_analyze API调试分词效果,实现“索引时扩展同义词、搜索时不带”的生产级方案,提升中文搜索与智能提示体验。

啊渊的专栏 316

C#使用opencv和Yolo模型识别车牌号

本文基于OpenCVSharp与OnnxRuntime,结合YoloV8n-pose_plate模型(检测车牌位置)和OCR模型(识别车牌文字),实现高效车牌识别。通过预处理、目标检测、NMS筛选及文字识别流程,最终输出车牌框位置与识别文本。代码封装良好,支持自定义路径与置信度阈值,具备实际应用价值。

lweiyue的专栏 176

C# NAFNet 图片去模糊

基于NAFNet与ONNX Runtime的C# WinForms图片去模糊工具,支持DirectML GPU加速与CPU回退,实现一键去模糊、大图分块处理、并排对比及拖拽打开。具备高DPI适配、自绘圆角界面、命令行批量处理等功能,适用于Windows 10/11系统,可灵活配置模型路径与分块大小,解决显存不足与边缘接缝问题。

hixiong123的博客 260

使用C#代码提取、修改或删除 Excel 中的超链接

通过 C# 和 VB.NET,可以方便地管理 Excel 文件中的超链接,包括提取、修改和删除等操作。提取超链接: 获取工作表中的超链接集合,读取每个超链接的地址和类型,并将相关信息保存到文本文件中。修改超链接: 更新超链接的显示文本和目标地址,确保链接信息准确。删除超链接: 移除指定的超链接,同时可以选择保留单元格中的原有显示文本,或清除单元格的全部内容。这些操作可以帮助开发人员更高效地管理 Excel 文档中的链接信息,减少重复的手动操作,也便于在数据迁移、文档维护和自动化报表处理等场景中使用。

2501_93070778的博客 236

C#: 控件不支持透明的背景色

把透明度固定为255。

海天鹰 44

week11-词云图

核心逻辑:词频越高,文字字号越大;适合快速看文本高频关键词(影评、评论、摘要文本非常适配 CommentInfo.csv)

m0_66244637的博客 140
上一篇: 深入理解ASP.NET Core Middleware:构建高效Web应用的关键组件
下一篇: 深入探# 深入探究.NET 的 IAsyncEnumerable:异步迭代的底层奥秘与高效实践
步步为营DotNet
博客等级 码龄1年 295粉丝 287原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值