首页 > 编程语言 >.NET C# 9.0 record和with的定义及使用

.NET C# 9.0 record和with的定义及使用

时间:2023-11-06 23:47:02浏览次数:38  
标签:FirstName string Language get C# record NET public

C# 9 引入record,它一种可以创建的新引用类型,而不是类或结构。 C# 10 添加了 record structs,以便可以将记录定义为值类型。 记录与类不同,区别在于record类型使用基于值的相等性。 两个记录类型的变量在它们的类型和值都相同时,它们是相等的。with 表达式在 C# 9.0 及更高版本中可用,使用修改的特定属性和字段生成其操作数的副本。本文主要介绍.NET C# 9.0 record和with的定义及使用。

1、record定义及使用

record类型的实际是一个引用类型 ,但具备值类型的行为。重写了Equals等对象类型的比较方法,在两个不同引用的record对象的内容相同时,对两者进行==比较,判断两者相等为true。重写了ToString()方法,便于输出属性内容。还重写了GetHashCode()Equals()方法。

1)定义record类型

public record Language
{
    public string LastName { get; }
    public string FirstName { get; }
    public Language(string first, string last) => (FirstName, LastName) = (first, last);
}

创建使用:

Language lang = new("JavaScript", "JS");//Language lang = new Language("JavaScript", "JS");

用对象初始化器进行初始化,则在属性中使用init关键字,

如下,

public record Language
{
    public string? FirstName { get; init; }
    public string? LastName { get; init; }
}
Language lang = new(){ FirstName = "JavaScript", LastName = "JS"};//Language lang = new(){ FirstName = "JavaScript", LastName = "JS"}

注意:由于有set访问器,所以它支持用对象初始化器进行初始化,如想用构造函数进行初始化,可以添加自己的构造函数。 init 就是自动生成了一个对 私有只读字段 的封装,多了一种让你初始化 只读字段 的方式。

上面定义是不可变类型record,定义可变类型rcord代码,如下,

public record Language
{
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
}

2)解构函数

record对象能解构成元组,需要为record添加解构函数Deconstruct。通过构造函数的参数传入,并通过位置解构函数提取出来。

public record Language
{ 
    public string FirstName { get; init; } 
    public string LastName { get; init; }
    public Language(string firstName, string lastName) 
      => (FirstName, LastName) = (firstName, lastName);
    public void Deconstruct(out string firstName, out string lastName) 
      => (firstName, lastName) = (FirstName, LastName);
}

使用:

var language = new Language("JavaScript", "JS"); // 位置构造函数
var (firstName, lastName) = person;                        // 位置解构函数

3)定义protected属性

可以使用更简单的方式,代码如下,

public record Language(string firstName, string lastName)
{
    protected string FirstName { get; init; } = firstName;
    protected string LastName { get; init; } = lastName;
}

4)record的面向对象

在面向对象方面,支持继承,多态等所有特性。record的基类也是objectrecord只能从记录继承,record不能定义为static的,但是可以有static成员。不能从类继承调用父类构造函数可以使用方式如下,

 public record Student(string firstName, string lastName, int ID) : Language(firstName, lastName);

2、with的使用

with表达式,用于拷贝原有对象,并对特定属性进行修改。在 C# 9.0 中,with 表达式的左侧操作数必须为with。 从 C# 10 开始,with 表达式的左侧操作数也可以为with或匿名类型。

using System;
public class InheritanceExample
{
    public record Point(int X, int Y);
    public record NamedPoint(string Name, int X, int Y) : Point(X, Y);
    public static void Main()
    {
        Point p1 = new NamedPoint("A", 0, 0);
        Point p2 = p1 with { X = 5, Y = 3 };
        Console.WriteLine(p2 is NamedPoint);  // output: True
        Console.WriteLine(p2);  // output: NamedPoint { X = 5, Y = 3, Name = A }
    }
}

对于引用类型成员,在复制操作数时仅复制对成员实例的引用。 副本和原始操作数都具有对同一引用类型实例的访问权限。

using System;
using System.Collections.Generic;
public class ExampleWithReferenceType
{
    public record TaggedNumber(int Number, List<string> Tags)
    {
        public string PrintTags() => string.Join(", ", Tags);
    }
    public static void Main()
    {
        var original = new TaggedNumber(1, new List<string> { "A", "B" });
        var copy = original with { Number = 2 };
        Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}");
        // output: Tags of copy: A, B
        original.Tags.Add("C");
        Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}");
        // output: Tags of copy: A, B, C
    }
}

 

标签:FirstName,string,Language,get,C#,record,NET,public
From: https://www.cnblogs.com/wwkk/p/17814071.html

相关文章

  • .NET(C#) LinkedList、Queue<T>和Stack<T>的使用
    本文主要介绍.NET(C#)中,LinkedList链表、Queue<T>队列和Stack<T>堆栈的使用,以及相关的示例代码。1、LinkedList(链表)链表中元素存储内存中是不连续分配,每个元素都有记录前后节点,节点值可以重复,不能通过下标访问,泛型的使用保证类型安全,可以避免装箱拆箱,找元素就只能遍历,查找不方......
  • AtCoder Beginner Contest 327
    A-ab题意:判断字符串中是否有“ab”或者是“ba“#include<bits/stdc++.h>usingnamespacestd;voidsolve(){ intn; cin>>n;strings; cin>>s; if(s.find("ab")!=s.npos||s.find("ba")!=s.npos){ cout<<"Yes"; }else{......
  • NSSCTF Round#11 Basic 密码个人赛复盘
    [NSSRound#11Basic]ez_encABAABBBAABABAABBABABAABBABAAAABBABABABAAABAAABBAABBBBABBABBABBABABABAABBAABBABAAABBAABBBABABABAAAABBAAABABAABABBABBBABBAAABBBAABABAABBAAAABBBAAAABAABBBAABBABABAABABAAAAABBBBABAABBBBAAAABBBBBAB第一眼培根密码试了试但不对,观察长度发现应......
  • .NET(C#) Linq GroupBy和GroupJoin的使用
    Linq是LanguageIntegratedQuery的简称,它是微软在.NETFramework3.5里面新加入的特性,用以简化查询查询操作。本文主要介绍.NET(C#)中Linq的GroupBy和GroupJoin操作符1、GroupBy操作符GroupBy操作符类似于SQL语言仲的GruopBy语句,这里的GroupBy操作符用于将输入序列中的元素进......
  • .NET(C#) Cast和OfType的使用
    Linq是LanguageIntegratedQuery的简称,它是微软在.NETFramework3.5里面新加入的特性,用以简化查询查询操作。本文主要介绍.NET(C#)中Linq的Cast和OfType操作符。1、Cast操作符Cast操作符用于将一个类型为IEnumerable的集合对象转换为IEnumerable<T>类型的集合对象。也就是非......
  • .NET(C#) Linq Range和Repeat的使用
    Linq是LanguageIntegratedQuery的简称,它是微软在.NETFramework3.5里面新加入的特性,用以简化查询查询操作。本文主要介绍.NET(C#)中Linq的Range和Repeat操作符。1、Range操作符Range操作符用于辅助生成一个整数序列。usingSystem;usingSystem.Collections.Generic;usi......
  • .NET(C#) 对象的拷贝(浅拷贝和深拷贝)
    本文主要介绍.NET(C#),对象的拷贝,包括浅拷贝和深拷贝,以及浅拷贝和深拷贝的实现方式,不同的实现方式之间的性能对比。1、浅拷贝和深拷贝浅拷贝是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用型字段则指复制它的一个引用到目标对象。如果改变目标对象中引用型字段的值......
  • C++模板显示指定类型时使用引用遇到的问题
    1.问题这里我想让模板函数接收int和char类型的参数,并进行相加,显示指定参数类型为int。第一个调用理论上会自动将char类型强转成int类型,后进行相加;第二个调用理论上会自动将int类型强转成char类型,后进行相加;但是报错Nomatchingfunctionforcallto'add_ab'template<typena......
  • HDFS Balancer存储水位稳定性原理与实践
    1.背景在HDFS分布式系统中,经常会上线新的datanode以环境集群容量不足的问题。但是往往旧datanode水位较高,甚至爆满无法写入,新datanode非常空闲,导致旧机器无法写入数据,集群的流量集中到新datanode中,造成新datanode网络延迟。为了解决上述问题,可以通过Balancer工具定时讲高水位dat......
  • 重学C语言——变量及其生命周期
    上一篇blog中,我们写了两个程序,一起来回顾一下~#include<stdio.h>intmain(){ inta=10; printf("%d\n",a); return0;}在这个程序中,我们定义了一个名为a的变量,并申请了4个字节的内存空间,用来存放10这个整数。#include<stdio.h>intmain(){ chara='h'; printf(......