本教程介绍如何在 C# 中创建类型。 你将编写少量的代码,然后编译并运行这些代码。 本教程包含一系列探索 C# 中不同类型的课程。 这些课程介绍了 C# 语言的基础知识。
前面的教程使用的是文本和数字。 字符串和数字是 简单的类型:它们每个存储一个值。 随着程序规模的扩大,需要使用更为复杂的数据结构。 在需要具有更多字段、属性或行为的数据结构时,C# 提供了可以定义的不同类型。 现在开始探讨这些类型。
在本教程中,你将:
- 创建和操作元组类型。
- 创建记录类型。
- 了解结构、类和接口类型。
先决条件
您必须拥有以下之一:
- 使用 GitHub Codespaces 需要一个 GitHub 帐户。 如果还没有帐户,可以在 GitHub.com 创建免费帐户。
- 安装了以下工具的计算机:
若要使用 codespaces,需要一个 GitHub 帐户。 如果还没有帐户,可以在 GitHub.com 创建免费帐户。
元组
若要使用教程环境启动 GitHub Codespace,请打开 教程 codespace 存储库的浏览器窗口。 选择绿色 “代码 ”按钮和 “代码空间 ”选项卡。然后选择该 + 符号以使用此环境创建新的 Codespace。 如果已完成本系列中的其他教程,则可以打开该代码空间,而不是创建新的代码空间。
加载代码空间时,在名为 tuples.cs 的教程文件夹中创建新文件。
打开新文件。
将以下代码键入或复制到 tuples.cs:
var pt = (X: 1, Y: 2); var slope = (double)pt.Y / (double)pt.X; Console.WriteLine($"A line from the origin to the point {pt} has a slope of {slope}.");通过在集成终端窗口中键入以下命令来运行程序:
cd tutorials dotnet tuples.cs元组是具有固定长度的有序数值序列。 元组的每个元素都有一个类型和一个可选名称。
小提示
在探索 C#(或任何编程语言)的过程中,可能会在编写代码时犯错。 编译器会发现这些错误并向你报告。 当输出包含错误消息时,请仔细查看示例代码和代码以查看要修复的内容。 你还可以要求科皮洛特找出差异或发现任何错误。 该练习有助于学习 C# 代码的结构。
在前面的代码后面添加以下代码以修改元组成员:
pt.X = pt.X + 5; Console.WriteLine($"The point is now at {pt}.");还可以使用
with表达式来创建一个新元组,它是原始元组的修改副本。 在现有代码之后添加以下代码,并在终端窗口中键入dotnet tuples.cs以查看结果:var pt2 = pt with { Y = 10 }; Console.WriteLine($"The point 'pt2' is at {pt2}.");元组
pt2包含X的pt值 (6),而pt2.Y是 10。 元组是结构类型。 换言之,元组类型没有string或int这样的名称。 元组类型由成员数(称为 arity)和这些成员的类型定义。 成员姓名是为了方便起见。 即使成员具有不同的名称,也可以将元组赋值给具有相同算式和类型的元组。可以在编写代码后添加以下代码:
var subscript = (A: 0, B: 0); subscript = pt; Console.WriteLine(subscript);通过在终端窗口中键入
dotnet tuples.cs来试用它。 变量subscript有两个成员,两者均为整数。 两者subscript和pt表示同一元组类型的实例:一个包含两个int成员的元组。元组很容易创建:可以声明多个用括号括起来的成员。 以下所有声明都定义了具有不同元数和成员类型的不同元组。
添加以下代码以创建新的元组类型:
var namedData = (Name: "Morning observation", Temp: 17, Wind: 4); var person = (FirstName: "", LastName: ""); var order = (Product: "guitar picks", style: "triangle", quantity: 500, UnitPrice: 0.10m);通过在终端窗口中再次键入
dotnet tuples.cs来尝试此更改。
虽然元组易于创建,但它们的功能有限。 元组类型没有名称,因此无法向值集传达含义。 元组类型不能添加行为。 当类型定义了行为时,C# 还可以创建其他类型。
创建记录类型
如果需要在同一结构中使用多个值,元组是个不错的选择。 它们是轻量级的,可以在使用它们时定义它们。 随着你的程序规模扩大,你可能会发现整个代码都在使用相同的元组类型。 如果你的应用在 2D 图形空间中工作,则表示点的元组可能很常见。 找到此模式时,可以声明 record 存储这些值并提供更多功能的类型。
添加以下代码来声明和使用
record类型来表示Point。public record Point(int X, int Y);上述代码必须位于源文件的底部。 类型声明(如
record声明)必须遵循基于文件的应用中的可执行语句。在声明前面
record添加以下代码:Point pt3 = new Point(1, 1); var pt4 = pt3 with { Y = 10 }; Console.WriteLine($"The two points are {pt3} and {pt4}");record声明是Point类型的一行代码,它将X和Y值存储在只读属性中。 只要使用该类型,就必须使用Point名称。 正确命名的类型(如Point)会提供有关如何使用该类型的信息。 其他代码演示如何使用with表达式创建新点,该点是现有点的修改副本。pt4 = pt3 with { Y = 10 }行中写道:“除了pt4被赋值为 10 之外,pt3的值与Y相同”。可以在一个with表达式中添加任意数量要更改的属性。前面的
record声明是一行以结尾;的代码。 可以通过声明record为 类型添加行为。 记录成员可以是函数或更多数据元素。 一个类型的成员在类型声明中,位于{和}字符之间。删除
;,并在record声明后添加以下代码行:{ public double Slope() => (double)Y / (double)X; }在
record声明之前,with表达式所在行之后添加以下代码:double slopeResult = pt4.Slope(); Console.WriteLine($"The slope of {pt4} is {slopeResult}");在终端窗口中键入
dotnet tuples.cs以运行此版本。你为代表 和
X值的Y添加了格式。 你将record定义为一个命名类型,并且包含一个成员用于计算斜率。record类型是record class的简写: 包含额外行为的class类型。也可以修改
Point类型,使其成为record struct:public record struct Point(int X, int Y)record struct是一种struct类型,包含添加到所有record类型中的额外行为。通过在终端窗口中键入内容
dotnet tuples.cs来试用此版本。
结构、类和接口类型
C# 中的所有具体命名类型都是 class 类型或 struct 类型,包括 record 类型。
class 是引用类型。
struct 是一个值类型。 值类型的变量在内存中内联存储实例的内容。 换言之,record struct Point 存储了两个整数:X 和 Y。 引用类型的变量存储指向实例存储空间的引用或指针。 换言之,record class Point 存储的是对内存块的引用,该内存块保存了 X 和 Y 的值。
实际上,这意味着值类型在分配时会被复制,但类实例的副本就是引用的副本。 复制的引用指向同一个点的实例,X 和 Y 的存储空间相同。
record 修改器指示编译器为你编写多个成员。 可以在基础知识部分的记录类型一文中了解更多信息。
在声明一个 record 类型时,你就声明了自己的类型应该使用一组默认行为来进行等价比较、赋值和复制该类型的实例。 当存储相关数据是你的类型的主要责任时,记录是最好的选择。 在添加更多行为时,请考虑使用 struct 或 class 类型,而不使用 record 修饰符。
当需要更复杂的功能时,可以对值类型使用 struct 类型,但其主要作用是存储值。 使用 class 类型使用面向对象的成语,如封装、继承和多态性。
还可以定义 interface 类型来声明不同类型必须实现的行为合约。
struct 和 class 类型都可以实现接口。
你通常会在大型程序和程序库中使用所有这些类型。 在安装 .NET SDK 后,可以使用基础知识部分的类教程来探索这些类型。
已完成“在 C# 中创建类型”教程。 可以在以下文章中了解有关 C# 中类型的详细信息:
清理资源
GitHub 会在 30 天不活动后自动删除 Codespace。 如果打算探索本系列中的更多教程,您可以保留 Codespace 配置。 如果已准备好访问 .NET 站点 来下载 .NET SDK,则可以删除 Codespace。 若要删除 Codespace,请打开浏览器窗口并导航到 Codespaces。 应该会在窗口中看到代码空间的列表。 在学习教程代码空间的条目中选择三个点(...),然后选择 “删除”。