C# 9.0的init访问器

不控制可变性

下面是我们最常见的属性声明方式,允许属性在类的内部和外部都可以读取和修改

public int Id { get; set; }
namespace Demo
{public class Company{public int Id { get; set; }public Company(){}public Company(int id){Id = id; // 可以在构造函数中设置}public void UpdateId(int newId){Id = newId; // 可以在类内部的方法中修改}}internal class Program{static void Main(string[] args){var company = new Company(1);Console.WriteLine(company.Id); // 输出:1company.Id = 2; // 可以在类外部修改Console.WriteLine(company.Id); // 输出:2// 使用对象初始化器语法,需要无参数构造函数var newCompany = new Company { Id = 6 };Console.WriteLine(newCompany.Id); // 输出:6newCompany.UpdateId(4); // 通过方法更新Console.WriteLine(newCompany.Id); // 输出:4}}
}

数据一致性问题:在某些情况下,属性不应该在对象生命周期内被随意修改。例如,Id属性通常用于唯一标识一个对象,如果允许在对象生命周期内修改它,可能导致数据不一致的问题

去掉set访问器

去掉set访问器,使得属性变为只读

namespace Demo
{public class Company{public int Id { get; }public Company(){}public Company(int id){Id = id; // 只能在构造函数中设置}// UpdateId 方法不能再修改 Id 属性,因为 get 访问器限制了修改// public void UpdateId(int newId)// {//     Id = newId; // 编译错误:不能修改只读属性// }}internal class Program{static void Main(string[] args){var company = new Company(1);Console.WriteLine(company.Id); // 输出:1// 下面这行代码会导致编译错误,因为 Id 属性是只读的// company.Id = 2; // 编译错误:不能修改只读属性// 下面这行代码会导致编译错误,因为对象初始化器不能设置只读属性// var newCompany = new Company { Id = 6 }; // 编译错误:不能使用对象初始化器设置只读属性var newCompany = new Company(6);Console.WriteLine(newCompany.Id); // 输出:6// newCompany.UpdateId(4); // 编译错误:不能修改只读属性// Console.WriteLine(newCompany.Id); // 输出:4}}
}

readonly

readonly指示只能在声明期间或在同一个类的构造函数中向字段赋值。 可以在字段声明和构造函数中多次分配和重新分配只读字段

namespace Demo
{public class Company{public readonly int Id = 666; // 使用 readonly 关键字,初始化默认值为 666public Company(){// 无参数构造函数使用默认值 666}public Company(int id){Id = id; // 可以在构造函数中设置新的值}// UpdateId 方法不能再修改 Id 字段,因为 readonly 限制了修改// public void UpdateId(int newId)// {//     Id = newId; // 编译错误:readonly 字段只能在构造函数中赋值// }}internal class Program{static void Main(string[] args){var initCompany = new Company();Console.WriteLine(initCompany.Id); // 输出:666var company = new Company(1);Console.WriteLine(company.Id); // 输出:1// 下面这行代码会导致编译错误,因为 Id 字段是只读的// company.Id = 2; // 编译错误:readonly 字段在构造函数外不可修改// 使用对象初始化器时不能设置 readonly 字段,因此需要使用构造函数// var newCompany = new Company { Id = 6 }; // 编译错误:readonly 字段不能使用对象初始化器设置}}
}

private

如果不想在类外部修改,我们也可以这样写

namespace Demo
{public class Company{public int Id { get; private set; }public Company() { }public Company(int id){Id = id;  // 可以在构造函数中设置}public void UpdateId(int newId){Id = newId;  // 可以在类内部的方法中修改}}internal class Program{static void Main(string[] args){var company = new Company(1);Console.WriteLine(company.Id); //输出:1company.UpdateId(4);Console.WriteLine(company.Id); // 输出:4var newCompany = new Company();//company.Id = 2; // 编译错误:外部不能修改}}
}

private set访问器,允许类内部修改属性,但外部不可修改,即保护内部状态,常见应用场景:计数器、状态管理等

init访问器

init访问器允许属性在对象初始化时设置,但在对象初始化完成后就不能再修改

using System;namespace Demo
{public class Company{public int Id { get; init; } // 使用 init 访问器,使得属性在初始化后不可修改public Company(){}public Company(int id){Id = id; // 可以在构造函数中设置}// UpdateId 方法不能再修改 Id 属性,因为 init 访问器限制了修改// public void UpdateId(int newId)// {//     Id = newId; // 编译错误:初始化后不可修改// }}internal class Program{static void Main(string[] args){var company = new Company(1);Console.WriteLine(company.Id); // 输出:1// 下面这行代码会导致编译错误,因为 Id 属性是只读的// company.Id = 2; // 编译错误:初始化后不可修改var newCompany = new Company { Id = 3 }; // 使用对象初始化器Console.WriteLine(newCompany.Id); // 输出:3// 下面这行代码会导致编译错误,因为 Id 属性是只读的// newCompany.Id = 4; // 编译错误:初始化后不可修改}}
}

init访问器在数据传输对象(DTO)和配置对象中的应用

数据传输对象(DTO)

数据传输对象(DTO)是用于在不同系统或不同层之间传递数据的简单对象。这些对象通常不包含任何业务逻辑,仅用于封装数据。使用init访问器可以确保DTO在创建后其属性不会被修改,从而保证传输数据的完整性和一致性

namespace Demo
{public class CustomerDto{public int Id { get; init; }public string Name { get; init; }public string Email { get; init; }}internal class Program{static void Main(string[] args){// 使用对象初始化器创建DTO实例var customer = new CustomerDto{Id = 1,Name = "John Doe",Email = "john.doe@example.com"};Console.WriteLine($"Customer: {customer.Id}, {customer.Name}, {customer.Email}"); // 输出:Customer: 1, John Doe, john.doe@example.com// customer.Name = "Jane Doe"; // 编译错误:初始化后不可修改}}
}

配置对象

配置对象通常用于存储应用程序的配置设置。这些设置在应用程序启动时加载,并在整个应用程序生命周期内保持不变。使用init访问器可以确保配置对象在初始化后,其配置属性不会被修改,从而防止在应用程序运行过程中意外更改配置

public class AppConfig
{public string ConnectionString { get; init; }public int MaxRetryCount { get; init; }public bool EnableLogging { get; init; }
}internal class Program
{static void Main(string[] args){// 使用对象初始化器创建配置对象实例var config = new AppConfig{ConnectionString = "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;",MaxRetryCount = 5,EnableLogging = true};// 输出:Config: ConnectionString=Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;, MaxRetryCount=5, EnableLogging=TrueConsole.WriteLine($"Config: ConnectionString={config.ConnectionString}, MaxRetryCount={config.MaxRetryCount}, EnableLogging={config.EnableLogging}");// config.MaxRetryCount = 10; // 编译错误:初始化后不可修改}
}

开始使用init访问器

在C#9.0中,引入了init访问器。使用此功能,有两个先决条件:

  1. 安装.NET 5+ SDK
  2. 安装Visual Studio 2019或更高版本

参考

  • C# Init-Only Setters 属性 — C# Init-Only Setters Property (loginradius.com)
  • C#中init()方法是起什么作用啊-CSDN社区
  • init 关键字 - C# reference | Microsoft Learn
  • 一看就懂——C#中readonly关键字_c# readonly关键字-CSDN博客
  • 只读关键字 - C# reference | Microsoft Learn
  • C#9.0:Init - Hello-Brand - 博客园 (cnblogs.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/18503.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

22.Volatile原理

文章目录 Volatile原理1.Volatile语义中的内存屏障1.1.volatile写操作的内存屏障1.1.1.StoreStore 屏障1.1.2.StoreLoad 屏障 1.2.volatile读操作的内存屏障1.2.1.LoadStore屏障1.2.2.LoadLoad屏障 2.volatile不具备原子性2.1.原理 Volatile原理 1.Volatile语义中的内存屏障 在…

用于生成 Avatar 的文本引导式情感和运动控制-InstructAvatar

网址 https://wangyuchi369.github.io/InstructAvatar/ 用于生成 Avatar 的文本引导式情感和运动控制 官网翻译 最近的会说话的头像生成模型在实现与音频的真实和准确的嘴唇同步方面取得了长足的进步,但在控制和传达头像的详细表情和情感方面往往存在不足&#…

APM2.8如何做加速度校准

加速度的校准建议准备一个六面平整,边角整齐的方形硬纸盒或者塑料盒,如下图所示,我们将以它作为APM校准时的水平垂直姿态参考,另外当然还需要一块水平的桌面或者地面 首先用双面泡沫胶或者螺丝将APM主板正面向上固定于方形盒子上&…

JavaScrip原型对象

参考 JavaScrip原型对象 | LogDicthttps://www.logdict.com/archives/javascripyuan-xing-mo-shi

每天写两道(二)LRU缓存、

146.LRU 缓存 . - 力扣(LeetCode) 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类: LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存…

如何使用Python和大模型进行数据分析和文本生成

如何使用Python和大模型进行数据分析和文本生成 Python语言以其简洁和强大的特性,成为了数据科学、机器学习和人工智能开发的首选语言之一。随着大模型(Large Language Models, LLMs)如GPT-4的崛起,我们能够利用这些模型实现诸多…

Revit——(2)模型的编辑、轴网和标高

目录 一、关闭缩小的隐藏窗口 二、标高(可创建平面,其他标高线复制即可) 三、轴网 周围的四个圈和三角表示四个里面,可以移动,不要删除 一、关闭缩小的隐藏窗口 二、标高(可创建平面,其他标…

计算机体系结构期末快速复习

文章目录 前言CPI,MIPS(大题1)加速比(大题2)流水线(大题3)CRAY-1向量机(大题4)Tomasulo算法(大题5)概念简答题计算机系统结构的经典定义什么是透明…

深入分析 Android Activity (二)

文章目录 深入分析 Android Activity (二)1. Activity 的启动模式(Launch Modes)1.1 标准模式(standard)1.2 单顶模式(singleTop)1.3 单任务模式(singleTask)1.4 单实例模式&#xf…

利用边缘计算网关的工业设备数据采集方案探讨-天拓四方

随着工业4.0时代的到来,工业设备数据采集成为了实现智能制造、提升生产效率的关键环节。传统的数据采集方案往往依赖于中心化的数据处理方式,但这种方式在面对海量数据、实时性要求高的工业场景时,往往显得力不从心。因此,利用边缘…

CSS实现一个雨滴滑落效果

使用纯CSS来实现一个真实的雨滴滑落效果可能会有些挑战,因为CSS主要关注于静态样式和简单的动画效果。然而,你可以使用CSS动画和keyframes来模拟一个雨滴滑落的简化效果。 以下是一个基本的示例,展示如何使用CSS来模拟雨滴从顶部滑落到底部的…

AI学习指南数学工具篇-MATLAB中的凸优化工具

AI学习指南数学工具篇-MATLAB中的凸优化工具 在人工智能领域,凸优化是一个非常重要的数学工具,它在机器学习、深度学习、数据分析等领域都有着广泛的应用。而MATLAB作为一款强大的数学工具软件,提供了丰富的凸优化工具和函数,为用…

二叉树的链式结构(二叉树)与顺序结构(堆)---数据结构

一、树的概念与结构 1、树的概念 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。我们常把它叫做树,是因为它看起来像一棵倒挂的树,它的根是朝上的,而叶是朝下的。 下面…

给我一个用断言结果执行下一步的例子

在使用 pytest 和 Selenium 进行自动化测试时,通常我们会根据断言的结果来决定测试流程的走向。如果断言失败,测试通常会停止执行后续的步骤,因为失败意味着被测系统没有按照预期工作。然而,有时候我们可能需要在断言失败后执行特…

每日复盘-20240528

今日重点关注: 20240528 六日涨幅最大: ------1--------300956--------- 英力股份 五日涨幅最大: ------1--------301361--------- 众智科技 四日涨幅最大: ------1--------301361--------- 众智科技 三日涨幅最大: ------1--------301361--------- 众智科技 二日涨…

前端编程语言——JS背景知识、JS基础语法、算数运算符和关系运算符(1)

0、前言: JS全称是JavaScript,是一种脚本语言,诞生于1995年,JS是由ECMAScript(包含js语法)、BOM(Brower Oject Model,和浏览器相关操作)、DOM(Document Obje…

ubuntu设置中文输入法教程

在 Ubuntu 上设置中文输入法可以通过以下步骤来完成。我们将以安装和配置 fcitx 输入法框架及其中文输入法插件 fcitx-sunpinyin 为例。 ### 步骤一:安装 fcitx 和中文输入法插件 1. **更新软件包列表** 打开终端并运行以下命令来更新软件包列表: …

浅谈—“文件映射”

目录 文件映射头文件&#xff1a; 核心函数 port flags 文件映射头文件&#xff1a; #include<sys/mman.h> 核心函数 void *mmap(void *addr,size_t length, int port,int flags,int fd, off_t offset ); int munmap(void *addr,size_t length);// 对比free&#x…

联邦和反射器实验

拓扑图 一.实验要求 1.AS1存在两个环回&#xff0c;一个地址为192.168.1.0/24&#xff0c;该地址不能在任何协议中宣告 AS3存在两个环回&#xff0c;一个地址为192.168.2.0/24&#xff0c;该地址不能在任何协议中宣告 AS1还有一个环回地址为10.1.1.0/24&#xff…

PyTorch训练关键点

1.背景 在网上找了一些资料用来训练关键点&#xff0c;一般都是人脸或者车牌关键点训练&#xff0c;或者是联合检测一起训练。很少有是单独基于轻量级网络训练单独关键点模型的工程&#xff0c;本文简单介绍一种简单方法和代码。 2.代码模块 &#xff08;1&#xff09;网络结…