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);
}
相关推荐
若水晴空初如梦6 分钟前
QT聊天项目DAY14
开发语言·qt
幼稚园的山代王10 分钟前
python3基础语法梳理(一)
开发语言·python
幼稚诠释青春32 分钟前
面试实例题
java·开发语言
weixin_4576653935 分钟前
C++11新标准
开发语言·c++
阿蒙Amon35 分钟前
C#封装HttpClient:HTTP请求处理最佳实践
开发语言·http·c#
大白爱琴1 小时前
使用python进行图像处理—像素级操作与图像算术(4)
开发语言·图像处理·python
虾球xz2 小时前
CppCon 2015 学习:Reactive Stream Processing in Industrial IoT using DDS and Rx
开发语言·c++·物联网·学习
aischang2 小时前
统信桌面专业版如何使用python开发平台jupyter
开发语言·python·jupyter·统信uos
狐凄3 小时前
Python实例题:Python计算概率论
开发语言·python·概率论