C# 结构体
最后修改于 2023 年 7 月 5 日
在本文中,我们将使用 C# 中的结构体类型。
结构体类型
结构体是一种值类型。该类型使用 struct
关键字定义。结构体类似于类。结构体旨在表示轻量级对象,例如 Point
、Rectangle
、Color
等。在许多情况下,结构体可能比类更有效率。结构体是值类型,并在堆栈上创建。请注意,像 int
、bool
、float
这样的原始数据类型在技术上都是 struct
类型。
所有 struct
类型都继承自 System.ValueType
,并进一步继承自 System.Object
。结构体永远不会是抽象的,并且总是隐式密封的。因此,结构体类型不支持继承。因此,struct
数据成员不能声明为 protected。抽象和密封修饰符不允许用于 struct
定义。struct
不允许声明无参数构造函数。
结构体还可以包含构造函数、常量、字段、方法、属性、索引器、运算符、事件和嵌套类型。但是,如果我们需要实现更多这些特性,我们可能需要考虑使用类来代替。结构体可以实现接口。struct
可以用作 nullable
类型,并且可以被赋予 null 值。
C# 结构体简单示例
以下示例创建一个简单的结构体。
var p = new Point(2, 5); Console.WriteLine(p); public struct Point { private int x; private int y; public Point(int x, int y) { this.x = x; this.y = y; } public override string ToString() { return $"Point x:{x}, y:{y}"; } }
该示例创建一个 Point
结构体。该点也可以用类来表示,但是使用 struct
我们可以更有效率;特别是,当我们处理大量点时。
var p = new Point(2, 5); Console.WriteLine(p);
我们创建 Point
结构体并调用其 ToString
方法。
public struct Point { ... }
该结构体使用 struct
关键字声明。
public override string ToString() { return $"Point x:{x}, y:{y}"; }
struct
类型不支持继承。但是,我们可以使用 override
关键字来覆盖该 struct
类型隐式继承的方法。 ToString
方法就是这种情况。
$ dotnet run Point x:2, y:5
没有 new 关键字
可以创建 struct
类型的实例,而无需使用 new
关键字。
Person p; p.name = "Jane"; p.age = 17; Console.WriteLine($"{p.name} is {p.age} years old"); public struct Person { public string name; public int age; }
我们有一个 Person
结构体,其中包含两个公共成员。
Person p;
首先,我们声明一个 Person
结构体。
p.name = "Jane"; p.age = 17;
稍后,我们使用一些数据初始化该结构体。
$ dotnet run Jane is 17 years old
C# 结构体自动实现的属性
我们可以将自动实现的属性与结构体类型一起使用。
var p1 = new Person("John Doe", "gardener"); Console.WriteLine(p1); var p2 = new Person("Roger Roe", "driver"); Console.WriteLine(p2); public struct Person { public Person(string name, string occupation) { this.Name = name; this.Occupation = occupation; } public string Name { get; set; } public string Occupation { get; set; } public override string ToString() { return $"{Name} is a(n) {Occupation}"; } }
在该程序中,我们有一个 Person
结构体类型,它具有自动实现的 Name
和 Occupation
属性。
public string Name { get; set; } public string Occupation { get; set; }
get
和 set
关键字用于创建自动实现的属性。我们有更简洁和可读的代码。
C# 只读结构体
使用 readonly
修饰符,我们可以创建不可变的结构体类型。只读结构体的所有成员都必须是只读的。字段成员也使用 readonly
修饰符,而自动属性也可以使用 init
关键字。
var p = new Point(3, 7); Console.WriteLine(p); public readonly struct Point { public Point(double x, double y) { X = x; Y = y; } public double X { get; init; } public double Y { get; init; } public override string ToString() { return $"({X}, {Y})"; } }
在该示例中,我们创建一个点。 Point
结构体具有两个只读属性:X
和 Y
。
public double X { get; init; } public double Y { get; init; }
init
关键字创建一个 init-only setter。它仅在对象构造期间为属性分配一个值。这强制执行不变性。
C# 结构体是值类型
结构体类型是值类型。它们在堆栈上创建。创建值类型时,仅分配一个内存空间来存储该值。值类型的赋值会复制该值。
var p1 = new Person("Beky", 18); var p2 = p1; Console.WriteLine(p2); p2.Name = "Jane"; p2.Age = 17; Console.WriteLine(p2); Console.WriteLine(p1); public struct Person { public Person(string name, int age) : this() { this.Name = name; this.Age = age; } public string Name { get; set; } public int Age { get; set; } public override string ToString() { return $"{Name} is {Age} years old"; } }
我们有一个 Person
结构体,其中包含两个数据成员。我们有一个双参数构造函数,并且我们还使用自动属性。
var p1 = new Person("Beky", 18); var p2 = p1;
在这里,我们创建一个 struct
。然后,将创建的 struct
分配给另一个 struct
。我们创建了该结构体的副本。
p2.Name = "Jane"; p2.Age = 17;
我们更改第二个结构体的数据。第一个结构体不受影响,因为我们处理的是原始 struct
类型的副本。
public string Name { get; set; } public int Age { get; set; }
自动属性可以在 struct
类型中使用。
$ dotnet run Beky is 18 years old Jane is 17 years old Beky is 18 years old
原始类型是结构体
像 int
、float
或 bool
这样的原始数据类型在底层都是结构体。这与 C++ 或 Java 等语言不同。
float x = 12.3f; int y = 34; bool z = false; Console.WriteLine(x.GetType()); Console.WriteLine(y.GetType()); Console.WriteLine(z.GetType());
我们有三个变量:一个 float、一个 int
和一个 bool
。我们对它们中的每一个都调用 GetType
方法。
Console.WriteLine(x.GetType());
我们对 float 值调用 GetType
方法。每个结构体都隐式地继承自包含 GetType
方法的 System.ValueType
类。
$ dotnet run System.Single System.Int32 System.Boolean
来源
在本文中,我们介绍了 C# 中的 struct 类型。
作者
列出所有 C# 教程。