C# --- Struct and Record

C# --- Struct and Record

Struct

  • struct是一种数据类型, 和class非常类似, 主要有以下的不同
  • struct是value type, class是reference type
  • 因为是value type所以strcut不是必须储存在heap上
  • struct不能等于null, The default value for a struct is an empty instance, with all fields empty (set to their default values).
  • struct 支持值比对, 也就是可以直接用等于号比较
  • struct 不支持继承
csharp 复制代码
struct Point
{
	 int x, y;
	 public Point (int x, int y) { this.x = x; this.y = y; } 
}

struct 的 default constructor

  • a struct always has an implicit parameterless constructor.
csharp 复制代码
Point p = new Point(); // p.x and p.y will be 0
struct Point { int x, y; }
  • Even when you define a parameterless constructor of your own, the implicit parameterless constructor still exists and can be accessed via the default keyword:
csharp 复制代码
Point p1 = new Point(); // p1.x and p1.y will be 1
Point p2 = default; // p2.x and p2.y will be 0
struct Point
{
	int x = 1;
	int y;
	public Point() => y = 1;
}

Record

  • record 是基于class和struct的数据类型, 也就是分为 class based record 和 struct based record, struct可以包含fields, properties, method等
  • record 可以实现interface, 也可以拥有继承关系 (class-based record)
  • record默认是class based record: record Point { } // Point is a class
  • struct based record: record struct Point { } // Point is a struct

一个简单的record

csharp 复制代码
record Point
{
	 public Point (double x, double y) => (X, Y) = (x, y); //(X, Y) = (x, y); 等于 { this.X = x; this.Y = y; }
	 public double X { get; init; }
	 public double Y { get; init; } 
}
  • 在编译阶段, 以上的代码会被加入, 如下代码所示
  • 编译器加入 protected copy constructor 和 hidden clone method 帮助实现 nondestructive mutation
  • 重写比较方法(equal, hashcode等方法) 帮助实现值对比
  • 重写toString() 方法
csharp 复制代码
class Point
{ 
	 public Point (double x, double y) => (X, Y) = (x, y);
	 public double X { get; init; }
	 public double Y { get; init; } 
	 protected Point (Point original) // "Copy constructor"
	 {
	 	this.X = original.X; this.Y = original.Y
 	 }
 	 // This method has a strange compiler-generated name:
	 public virtual Point <Clone>$() => new Point (this); // Clone method
 	// Additional code to override Equals, ==, !=, GetHashCode, ToString()
 	// ...
}

record的parameter list

  • record的后面可以用括号包括parameter list, 在初始化时可以直接 var = new Point(12, 4)
csharp 复制代码
record Point (double X, double Y)
{
 // You can optionally define additional class members here...
}
  • 编译器会对parameter list进行如下操作
  • 给每个parameter构建 init-only property
  • 构建primary constructor
  • 构建deconstructor

Nondestructive Mutation

  • 当我们需要对一个immutable object进行修改的时候, 我们需要创建一个新的object然后对原来的object进行copy以及修改, 这就是Nondestructive Mutation. 但是当property很多的时候, 就会很麻烦
  • record提供了更便捷的方法实现 Nondestructive Mutation, 使用with keyword
csharp 复制代码
Point p1 = new Point (3, 3);
Point p2 = p1 with { Y = 4 };
Console.WriteLine (p2); // Point { X = 3, Y = 4 }
record Point (double X, double Y);
  • In this example, p2 is a copy of p1, but with its Y property set to 4. The benefit is
    more apparent when there are more properties:
csharp 复制代码
Test t1 = new Test (1, 2, 3, 4, 5, 6, 7, 8);
Test t2 = t1 with { A = 10, C = 30 };
Console.WriteLine (t2);
record Test (int A, int B, int C, int D, int E, int F, int G, int H);
//Here's the output:
Test { A = 10, B = 2, C = 30, D = 4, E = 5, F = 6, G = 7, H = 8 }

Record and Equality Comparsion

  • record在编译时, 编译器会重写equal, hashcode等比较方法, 所以可以直接比较, 不需要像reference type一样重写equal和hashcode.
csharp 复制代码
var p1 = new Point (1, 2);
var p2 = new Point (1, 2);
Console.WriteLine (p1.Equals (p2)); // True
record Point (double X, double Y);
  • The equality operator also works with records (as it does with tuples):
csharp 复制代码
Console.WriteLine (p1 == p2);  // True
  • 如果record包含 lazy values, transient' value, arrays, 或者 collection type 或者 自定义的等于比较时, 需要重写equals 当然也需要重写GetHashCode()
csharp 复制代码
record Point (double X, double Y)
{
	double _someOtherField;
	public virtual bool Equals (Point other) =>
	other != null && X == other.X && Y == other.Y;
}

Use case

csharp 复制代码
public record settingscope( [property: BsonIgnoreIfNull] string IdSettingscopeType Type)
{
	public static Settingscope Global { get; } = new(null, SettingScopeType.Global);
}
相关推荐
暮乘白帝过重山1 天前
ArkTS ForEach 参数解析:组件与键值生成器
开发语言·数据库
LiamTuc1 天前
Java构造函数
java·开发语言
三途河畔人1 天前
Pytho基础语法_运算符
开发语言·python·入门
Benmao⁢1 天前
C语言期末复习笔记
c语言·开发语言·笔记·leetcode·面试·蓝桥杯
adsadswee1 天前
Qt 样式与 QLinearGradient 渐变详解
开发语言·qt·qt样式表·qlineargradient·qss渐变效果
花月C1 天前
个性化推荐:基于用户的协同过滤算法
开发语言·后端·算法·近邻算法
脾气有点小暴1 天前
前端页面跳转的核心区别与实战指南
开发语言·前端·javascript
rit84324991 天前
基于MATLAB的BP神经网络手写数字识别
开发语言·神经网络·matlab
San30.1 天前
深入 JavaScript 内存机制:从栈与堆到闭包的底层原理
开发语言·javascript·udp
灰灰勇闯IT1 天前
RN路由与状态管理:打造多页面应用
开发语言·学习·rn路由状态