C#知识学习-003

1. 元组

1.1 什么是元组

元组是具有固定长度的有序数值序列。 元组的每个元素都有一个类型和一个可选名称。

举个例子帮你理解 (顺便帮你回忆一下上一篇的内容):

var pt = (X: 1, Y: 2);

var slope = (double)pt.Y / (double)pt.X;
Console.WriteLine($"point is {pt} and slope is {slope}.");

1.2 如何修改

你还可以重新分配元组中的任何成员

var pt = (X: 1, Y: 2);
pt.X = pt.X + 5;
Console.WriteLine($"point is {pt}.");

 1.3 元组类型

元组是结构类型。 换言之,元组类型没有 string 或 int 这样的名称。

元组类型由成员数(称为 arity)和这些成员的类型定义。 成员姓名是为了方便起见。

即使成员具有不同的名称,也可以将元组赋值给具有相同算式和类型的元组。

别担心,我来举例让你更好理解:

var pt = (X: 1, Y: 2);
var subscript = (A: 0, B: 0);
subscript = pt;
Console.WriteLine($"point is {pt}.");
Console.WriteLine($"subscript is {subscript}.");

 也就是:首先,变量 subscript 有两个成员,两者均为整数。 

其次,subscript 和 pt 表示同一元组类型的实例,因其都是包含 2 个 int 成员的元组

即使两者的成员具有不同的名称,所以可以进行赋值

1.4 创建元组

元组很容易创建:可以声明多个用括号括起来的成员。

举几个例子:

var point = (10, 20);             // 无名元组
var namedData = (Name: "Bo luo", Temp: 2, Wind: 10);
var person = (FirstName: "", LastName: "");
var order = (Product: "cat", style: "cute", quantity: 500, Price: 0.10m);

1.5  with 表达式

还可以使用 with 表达式来创建一个新元组(pt2就是新元组)

它是原始元组的修改副本。(pt2就是pt的修副本,我们把Y的值改成了10)

var pt = (X: 1, Y: 2);
var pt2 = pt with { Y = 10 };
Console.WriteLine($"point is {pt}.");
Console.WriteLine($"pt2 is {pt2}.");

1.6 创建记录类型

虽然元组很容易创建,但功能有限。

官方说法:元组类型没有名称,因此无法向值集传达含义。 元组类型不能添加行为。

(可能有点晕,不过我会尽量的解释,希望能帮到你)

我们用这个元组举例:var catFood = (猫粮: 2, 冻干: 3); 

元组就像是你写给自己的纸条(猫粮2个,冻干3个)
补充一个概念:函数(Function)- 目前知道有它即可

函数就类似于你教其他人喂猫的步骤

void 喂猫步骤(int 食物1的数量,int 食物2的数量)
{
    1.喂猫粮
    2.喂冻干
    3.陪“菠萝”玩
}

那么此时会有一个问题,传递时只能传递数值部分,名称部分是不知道的

你传递给其他人的步骤是:喂猫步骤(2,3);

其他人拿到数据后,完全分不清到底是两个猫粮还是两个冻干

这就是元组的功能有限,此时可以通过record来解决问题!

方式过程结果
寄实物箱子装上2猫粮+3冻干(贵,慢)✅ 收到直接认识
寄纸条"2,3"只写两个数字❌ 不知道是什么

​寄纸条(元组)

"(猫粮:2,冻干:3)"​

名字写在纸条上❌ 但运输公司会撕掉名字标签

​寄正式购物清单

(record)​

列出:
• 猫粮:2
• 冻干:3
✅ 保留名称和数量

 record 声明是 foodBook类型的这一行代码,它将 猫粮数量和 冻干数量 值存储。

我们为代表 猫粮数量 和 冻干数量 值的元组添加了格式

让它成为一个 record,定义了一个命名的类型(创建专属名称“foodBook”)

只要使用该类型,就必须使用 foodBook名称

// 创建食材本(record)
record foodBook(int 猫粮数量, int 冻干数量);

void 喂猫步骤(foodBook 今天食材)
{
    Console.WriteLine($"用{今天食材.猫粮数量}个猫粮");
    Console.WriteLine($"打{今天食材.冻干数量}个冻干");
}

//2对应了猫粮,3对应了冻干
var 今日任务 = new foodBook(2, 3);
喂猫步骤(今日任务);

当只需要数字时用元组,当需要表达"这是什么"时一定用record!(希望这个例子有帮助)

关于添加行为:

记录成员可以是一个函数(比如下例中的打印总数量)

也可以是多个数据元素(之后学习,目前知道即可)

一个类型的成员在类型声明中,位于 {  } 字符之间。

// 创建食材本(record)
record foodBook(int 猫粮数量, int 冻干数量)
{
    void 打印总数量()
    {
        Console.WriteLine($"总数量{猫粮数量 + 冻干数量}");//结果是5
    }
}

//2对应了猫粮,3对应了冻干
var 今日任务 = new foodBook(2, 3);

//调用食材本中的方法
今日任务.打印总数量();

补充一点知识,防止混淆:

函数 vs 方法

关于函数(独立存在)

// 独立函数(不属于任何类型)
void 打印总数(int 猫粮, int 冻干)
{
    Console.WriteLine($"总数量{猫粮 + 冻干}");
}

// 调用方式(直接调用)
打印总数(2, 3); // 输出:总数量5

方法(​定义在记录内部​​ → 属于 foodBook 类型):

record foodBook(int 猫粮数量, int 冻干数量)
{
    // 记录内部的方法
    public void 打印总数量()
    {
        Console.WriteLine($"总数量{猫粮数量 + 冻干数量}");
    }
}

// 调用方式(通过对象调用)
var 今日任务 = new foodBook(2, 3);
今日任务.打印总数量(); // 输出:总数量5

记住这个简单规则:

  • 看到 对象.名字() → 这是方法
  • 看到 名字() → 这是函数

2. 结构、类和接口类型

record 类型是 record class 的简写: 包含额外行为的 class 类型。

也可以修改,使其成为 record struct

接下来我会换一种例子分别解释: 

2.1 record struct(值类型记录)

record struct Point(int X, int Y); 

// 使用
var p1 = new Point(1, 2);
var p2 = p1; // 值复制:p2 是独立副本
p2.X = 3;    // 不影响 p1
Console.WriteLine(p1);      // 输出:Point { X = 1, Y = 2 }
Console.WriteLine(p1 == p2); // 判断是否相等,结果:false(基于值比较)

 2.2 record class(引用类型记录)

record class Point(int X, int Y);

// 使用
var p1 = new Point(1, 2);
var p2 = p1; // 复制引用(指向同一对象)
// p2.X = 3; ❌ 错误!默认不可变
var p3 = new Point(1, 2);
Console.WriteLine(p1 == p2); // true(同一实例)
Console.WriteLine(p1 == p3); // true(值相同,与引用无关)

 ​​简单决策法​​:

  • 需要​​内存高效+频繁复制​​ → 选 record struct
  • 需要​​共享数据+不可变性​​ → 选 record class

C# 中的所有命名类型都是 class 或 struct 类型。 class 是引用类型。 struct 是一个值类型

值类型的变量在内存中内联存储实例的内容。

换言之,record struct Point 存储了两个整数:X 和 Y

引用类型的变量存储指向实例存储空间的引用或指针。

换言之,record class Point 存储的是对内存块的引用,该内存块保存了 X 和 Y 的值。

 学到了这里,咱俩真棒,记得按时吃饭(北京今天下大雨,上班是牛马,下班是河马)

【本篇结束,新的知识会不定时补充】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值