C# 学习笔记
第一个C# 程序
那么常规操作,第一步打印Hello World
1 | using System; |
这个写法是不使用顶级语句
的,在C# 9.0
引入了顶级语句,可以省略类和Main
方法,直接写代码
注释
接下来看注释
,注释与Java
类似,分为单行注释
和多行注释
//
单行注释
/* ... */
多行注释
///
用于注释类、方法、属性等,可以自动生成文档,这个是C#
特有的,在类、方法上面敲入三个斜杠,即可自动生成注释模板
1 | // 命名空间引用 |
控制台相关内容
现在我们主要编写控制台应用,所有得来了解了解控制台相关的东西
输入输出
WriteLine
输出并自动换行
Write
输出但不换行
ReadLine
获取输入,并自动换行,直到用户按下回车键
ReadKey
获取输入,用户按下任意键就继续执行
1 | // 打印Hello, World!(并自动空行) |
获取输入但不显示
如果你不希望用户输入的内容显示在控制台上,可以使用ReadKey(true)
,
这样用户输入的内容就不会显示在控制台上,而是存储在KeyChar
属性中,返回为char
类型
1 | char c = Console.ReadKey(true).KeyChar; // 获取用户输入的字符,不显示在控制台上 |
清空控制台
Clear
清空控制台
1 | Console.Clear(); |
控制台窗口
设置控制台大小
SetWindowSize
设置控制台大小,参数为宽
和高
1 | Console.SetWindowSize(80, 30); |
设置控制台缓冲区大小
SetBufferSize
设置控制台缓冲区大小,参数为宽
和高
注意,缓冲区大小不能小于
控制台大小,否则会报错
1 | Console.SetBufferSize(80, 30); |
退出控制台
Exit
退出控制台
1 | Console.Exit(0); |
光标
设置光标位置
窗口中,左上角坐标为(0,0)
,向右为X轴正方向
,向下为Y轴正方向
SetCursorPosition
设置光标位置,参数为横坐标和纵坐标,单位为字符
1 | Console.SetCursorPosition(10, 5); |
在视觉上,1y = 2x,所以要想让光标起始位置看起来像个正方形,就得将x坐标设置为y坐标的两倍
隐藏光标
CursorVisible
设置光标是否可见,参数为布尔值
1 | Console.CursorVisible = false; |
颜色
文字颜色
ForegroundColor
设置文字颜色,参数为枚举类型ConsoleColor
,默认为白色
1 | Console.ForegroundColor = ConsoleColor.Red; |
背景颜色
BackgroundColor
设置背景颜色,参数为枚举类型ConsoleColor
,默认为黑色
注意设置好背景颜色之后,需要Clear
一次,才能看到效果
1 | Console.BackgroundColor = ConsoleColor.Blue; |
折叠代码
与直接折叠大括号{}
中的代码不同,C#提供了#region
和#endregion
来折叠代码
你可以在代码中直接使用它们来自定义你要折叠的代码块
以#region
开头,以#endregion
结尾,可以折叠代码,方便阅读
执行编译时,#region
和#endregion
会被忽略,不会影响代码的执行
1 |
|
数据类型
好,接下来我们来看看C#的数据类型
有符号整型
有符号整型是可正
可负
的
sbyte
-128~127,占用1字节
short
-32768~32767,占用2字节
int
-2147483648~2147483647,占用4字节
long
-9223372036854775808~9223372036854775807,占用8字节
1 | // 有符号的整型sbyte short int long |
无符号整型
那么顾名思义,它就是非负
的整型
不过它所代表的数值的数量是和有符号整型一样的
byte
0~255,占用1字节
ushort
0~65535,占用2字节
uint
0~4294967295,占用4字节
ulong
0~18446744073709551615,占用8字节
1 | // 无符号的整型byte ushort uint ulong |
浮点型
浮点数,即小数
,它分为单精度
和双精度
float
7~8位有效数字(有效数字:从第一位非零数字起算
),需加f
,占用4字节
double
15~16位有效数字,写小数时,默认为此类型,其他两个的需要指定,占用8字节
decimal
28~29位有效数字,需加m
,占用16字节
1 | // 浮点型 float double decimal |
字符型
char
只能存储一个字符,只能用单引号括起来,占用2字节
1 | // 字符 |
布尔型
bool
true/false,占用1字节
1 | // 布尔 |
字符串
字符串类型的,一般用双引号
括起来,可以存放多个字符,没有固定的占用字节数,根据内含字符的数量来决定的
string
字符串
1 | // 字符串 |
变量初始化
一般来说,变量声明后就得初始化
;亦可先定义,再初始化
1 | int a = 100; |
先定义,再初始化
1 | int a; |
但不论如何,使用变量之前必须
初始化
另外,可以连续声明相同类型
的变量,用逗号隔开
1 | int a = 100, b = 200, c = 300; |
变量命名规范
- 变量名必须以字母、下划线开头
- 变量名只能包含字母、数字、下划线,并区分大小写,不能重复
- 变量名不能使用关键字
- 变量名应当顾名思义
- 一般遵循驼峰命名法,即首字母小写,后续每个单词首字母大写(函数、类可采用大驼峰命名法)
常量
常量,即不可改变的量,用const
关键字定义,必须初始化,不能修改
1 | const int months = 12; |
转义字符
转义字符,即用反斜杠\
开头的字符,用于表示一些特殊字符
\n
换行\t
制表符\\
斜杠\"
双引号\'
单引号\b
光标退格\0
空字符\a
警报音
1 | Console.WriteLine("换行符\n换行"); |
类型转换
隐式转换
隐式转换为程序帮助我们转换,而不用我们手动转换
值得注意的是,数据类型——大范围装小范围
1 | int a = 10; |
在上面的例子中,a
可以隐式转换为long
类型的
但a
隐式转换为short
类型的,因为short
的范围小于int
的范围
同样的,还有以下注意事项
1 | // decimal不能隐式转换double和float,但整型可以被转换 |
显式转换
显示转为为强制转换,用括号()
变量类型 变量名 = (目标类型)变量名
但要注意的是,强制转换可能导致溢出
的问题,需要注意转换类型之间的范围
同时,其精度
也有可能丢失
1 | int o = 10; |
变量类型.Parse()
方法可以将字符串转换为其他类型
1 | int q = int.Parse("123"); |
Convert.ToXXX()
方法可以更准确地转换变量类型
每一种类型都有对应的Convert.ToXXX()方法
1 | int u = Convert.ToInt32("123"); |
所有类型都可以通过ToString()
方法转换为字符串
1 | int a1 = 123; |
另外,补充说明以下,Console.ReadLine()
方法会读取用户输入的字符串,并返回一个string
类型
异常捕获
在程序运行时,有可能会出现一些错误
,导致程序无法正常运行
而有时候我们需要将出现的问题输出,更为具体地通俗易懂地告诉用户出现了什么问题(毕竟报错信息并不是所有人都看得懂的)
这个情况下,我们就要使用try-catch
语句
try
语句块中,我们放置可能会出现异常的代码,而catch
语句块中,我们放置处理异常的代码
另外还有finally
语句块,无论是否出现异常,都会执行finally
语句块中的代码
1 | // 基本语法 |
运算符
赋值运算符
赋值运算符,即=
,将右边的(表达式)值赋给左边的变量
1 | int a = 10; |
不论=
右边是什么,都是先运算右边的,再赋值给左边的变量
算术运算符
就像数学中的加减乘除,在程序中也有对应的
+
加、-
减、*
乘、/
除、%
取余(即除不尽的则取它的余数,除得尽的为0)
1 | int a = 1; |
自增自减运算符
自增运算符,即++
,将变量值加1;
自减运算符,即--
,将变量值减1
但它们与变量的位置不同,结果也不同
1 | int a = 1; |
复合运算符
它是=
和算术运算符的结合,用于简化代码
+=
加等、-=
减等、*=
乘等、/=
除等、%=
取余等
1 | a += b; // 等效 a = a + b; |
关系运算符
关系运算符,用于比较两个值的大小关系,结果为bool
类型
==
等于、!=
不等于、>
大于、<
小于、>=
大于等于、<=
小于等于
1 | int h = 3; |
任意数值可以直接进行比较
但特殊类型string
、char
、bool
只能同类型
进行==
、!=
比较
逻辑运算符
逻辑运算符,用于连接多个条件,结果为bool
类型
&&
逻辑与(and)、||
逻辑或(or)、!
逻辑非(not)
1 | Console.WriteLine(a > h && b > h); |
其中,逻辑非!
的优先级最高,逻辑与&&
的优先级次之,逻辑或||
的优先级最低
位运算符
位运算符,用于对二进制位
进行操作,结果为int
类型
&
按位与、|
按位或、^
按位异或、~
按位取反、<<
左移、>>
右移
1 | int i1 = 2; |
三目运算符
表达式1 ? 表达式2 : 表达式3
如果表达式1为真,则返回表达式2的值;如果表达式1为假,则返回表达式3的值
1 | int k = 1; |
字符串拼接
字符串拼接可以用算术运算符的+
,将两个字符串连接在一起
1 | string str = "hello"; |
也可以使用{}
占位符,对字符串进行格式化,占位符中放置从0
开始的索引,表示要插入的变量
1 | string str1; |
括号
括号()
用于改变运算符的优先级,括号内的表达式先运算
1 | a = (c + d) * e; |
运算优先级(只包括上面提到的)
括号(最高优先级)
()
- 强制改变运算顺序自增/自减运算符
x++ x--
(后缀)++x --x
(前缀)算数运算符
* / %
(乘、除、取模)+ -
(加、减)位运算符
<< >>
(位移)&
(按位与)^
(按位异或)|
(按位或)关系运算符
< > <= >=
相等运算符
== !=
逻辑运算符
&&
(逻辑与)||
(逻辑或)条件运算符(最低优先级)
?:
(三元运算符)
流程控制
if语句
if
语句用于根据条件执行不同的代码块
1 | 语法: |
1 | if (true) |
if-else语句
1 | 语法: |
1 | int a = 1; |
if-else if-else语句
1 | 语法: |
1 | if (a > 5) |
switch语句
switch
类似于简化的if-else if-else语句,用于根据不同的条件执行不同的代码块
1 | 语法: |
case
判断的是表达式所得的值
是否与所写的常量值
一致,后面只能写常量,而不能写表达式或者变量
同样的,C#
的switch
语句需要写break
,不然会贯穿
即执行完一个case
后,会继续执行下一个case
,直到遇到break
或者switch语句结束
1 | a = 100; |
while循环
while
循环用于在条件为真
时重复执行代码块
但要注意,如果条件永远为真
,那么将导致死循环
,直至内存溢出,程序崩溃
1 | 语法: |
1 | int i = 0; |
break
break
用于跳出
循环,即当满足某个条件时,跳出循环,不再执行循环内的代码
1 | while (true) |
continue
continue
用于跳过
本次循环,即当满足某个条件时,跳过本次循环,继续下一次循环
1 | int a = 0; |
do-while循环
do-while
循环与while
循环类似,但它在循环体执行完毕后,再判断条件是否为真,即无论如何都会执行一次循环体
1 | 语法: |
1 | int b = 0; |
for循环
for
循环用于在指定次数内重复执行代码块
1 | 语法: |
1 | for (int c = 0; c < 10; c++) |
控制台小项目#1-移动小方块
需求
控制台显示一个小方块■
,用户输入w
、s
、a
、d
,控制小方块上下左右移动
实现
控制台
首先我们设置一下控制台的相关内容
重新设置背景颜色,设置文字颜色,并隐藏光标
1 | // 设置背景颜色 |
绘制小方块
接下来我们绘制小方块
1 | int x = 0; |
不过,对于一个游戏来说,肯定是有循环层
的,不然玩家输入一次那就没了可不行
拿Minecraft
来说,有一个东西名为tick
,刻
。它又分为随机刻
、游戏刻
等。
游戏刻为20
tick,即程序每秒将执行20
次,以实时改变游戏中的一些东西,
如玩家位置、更新方块等。游戏的循环会一直持续下去,直到玩家退出游戏
所以,我们要将绘制小方块的代码放入循环语句中,一般我们就采用while (true)
循环
1 | int x = 0; |
获取用户输入
接下来,在控制小方块移动之前,我们得先获取用户输入
1 | char c = Console.ReadKey(true).KeyChar; |
这里我们使用ReadKey(true)
不显示输入的字符,同时设置一个char c
变量来接收用户输入的字符
移动小方块
接下来,我们根据用户输入的字符,来移动小方块
那么我们输入的字符只有WASD
及wasd
8种,所以我们可以使用switch
语句来处理
1 | switch (c) |
这里我们就直接利用switch
贯穿的特性,即同一个字符的大小写都由同一块代码块来执行
随后,我们在各个case
中,根据用户输入的字符,来改变小方块的坐标
1 | switch (c) |
好,现在我们输入WASD
,小方块会根据输入的字符来移动,但是小方块不会消失,
所以我们需要在每次移动之前,将小方块原来
的位置清空
1 | while (true) |
擦除的话就直接写入空格即可,就可以将原来的位置的字符替换掉
限制移动范围
还没结束嘞!
当我们在在边缘位置移动小方块时,假设小方块此时贴在右边界
,
而我们没注意,继续按D
(d),那么小方块就会超出控制台的范围
,导致程序崩溃
所以,在各个case
语句中,我们还得判断下一个坐标是否越界
1 | switch (c) |
完整代码
1 | namespace XM1 |
控制台小项目#2-打Boss拿宝箱
需求
- 小项目分为
3
个界面,开始界面
、游戏界面
、结束界面
- 开始界面在上方中央位置显示
给木
,在下方显示开始游戏
、退出游戏
,玩家使用W
或S
进行选择,J
键确认 游戏界面
中,边界有红色的■
代表边界墙,下方留出一块区域用于输出信息- 玩家用黄色的
●
表示,用户输入WASD
控制小方块移动,只能在边界墙的范围内移动 - 生成一个
Boss
,用绿色的■
表示,当用户在Boss
边上时,按J
键进入对战状态 - 对战状态时,玩家不能移动,按
J
键攻击,玩家随机给Boss
造成伤害,而后Boss
对玩家造成伤害 当一方的攻击力小于对方防御力时,无法对对方造成伤害
- 当
玩家
血量小于等于0
时,游戏结束,进入结束场景
- 当
Boss
血量小于等于0
时,游戏结束,玩家可以移动,生成一个宝箱
,玩家到宝箱边上时,打开宝箱,游戏结束,进入结束场景 - 结束场景上方中央位置根据输赢显示
相应文字
,在下方显示重新开始
、退出游戏
,玩家使用w或s进行选择,j键确认
场景框架
这个小项目是比上面那个复杂得多了,不过不要捉急,我们拆解开一步步来
这个小项目是完全可以用上面已经提及的知识写出来的,未来会有更加复杂的小项目
前面我们已经写了一个控制玩家移动
的小项目了,至少在玩家移动上是没有多大的问题了
现在,这个小项目分为了3
个场景,除了第二个
游戏场景需要实现一定的逻辑外,
其他两个场景还是比较简单的
显示的文字可以直接用控制台打印的方法输出,玩家输入字符也有相应的判断方法
但是场景间该怎么切换呢?流程控制
,不过我们需要一个标识符
(变量
)来判断当前处于哪个场景
好,那么到这里,我们大体上是可以开始写代码了,我们先为这3
个场景打一个基本的框架,
再往里面填充东西
控制台基础设置
(以下代码均写在主函数Main
中,毕竟现在也还没学到函数部分)
常规的还是控制台的一些设置,比如设置窗口大小
、文字颜色
、隐藏光标
等
1 |
|
场景循环判断
好了,接下来就是场景的部分了
上面说了,我们需要一个标识符
用于判断当前的场景,所以我们就定义一个int
类型的变量吧
1 | int nowId = 1; |
那么再后面,就是游戏的循环层了,也就是while(true)
,直到你退出游戏前,这个循环都不会停止
那么,在循环中,我们就得用流程控制
来判断上面的标识符
,
再根据不同的标识符
处理不同场景的逻辑
这里流程控制的话,我选择使用switch
语句,因为的标识符是有限的
,且可以枚举出来的
1 | while (true) |
开始场景
那么接下来我们就来写第一个场景
不过在开始之前,建议是先执行清空控制台
的命令,因为我们最后可能是会从第三个场景
返回第一个场景
的,
得把前面的场景给先清空
1 | Console.Clear(); |
打印“给木”
接下来就是打印“给木”(其实就是Game
的音译)了,我们得先设置光标位置
,
用Console.SetCursorPosition
方法
1 | Console.SetCursorPosition(w / 2 - 2, 8); |
这里我们将光标位置设置到当前窗口一半
,再往左2
个字符(因为中文字符
是占2
个的)的位置,
高度上暂且设置为8
,具体的可以根据大家实际情况调整
打印选项
那么接下来就是打印开始游戏
和退出游戏
这两个选项了
大致也和上面的类似
1 | // 设置“开始游戏” |
不过现在,我们启动调试,也就只是打印了文字
,我们输入WS
也是没有反应的,所以下一步就是要获取用户输入
,并将用户当前选择的选项高亮显示
(换个颜色
)
获取用户输入
在获取用户输入之前,我们肯定得先写一个while
循环,毕竟总不能按一次就没了吧
用户输入WS
,选择选项,直到用户输入了J
键,我们才跳出循环,进入相应的场景
1 | while (true) |
不过,我们还得要一个变量
,用于记录用户当前选择的选项,然后用户按WS
时,改变这个变量的值
当然,这个变量的值我们不能
让它无限
地增大或者减少,所以在判断玩家输入的同时,
也要加个判断来限制它的范围
至于玩家的输入么,还是用switch
来判断好了
1 | int nowSelectId = 0; |
注意我们上面所说的变量,它是在while
外面的,不然每次循环它都会被重置,那就没有意义了
不过现在,我们尚未实现让玩家当前选择的选项高亮显示
,所以我们现在运行也不知道玩家选了什么
这里我们就要在各个选项打印之前来判断一下,选择的是否是这个选项,再改个颜色
1 | Console.ForegroundColor = |
这里我们运用三目运算符
来进行判断,以开始游戏
为例,
如果当前选择的选项是开始游戏
,即选项的标识符为0
,那么我们就将颜色设置为红色
,否则就是白色
下面的退出游戏同理
那么现在进行测试,我们按下WS就可以看到选项在变化了,不过,当我们在开始游戏按下J
之后,还在当前界面
为什么呢?因为我们没有
退出这个场景的循环,即便你在switch
的最后一个case
的if
中加入break
,也还是不行
因为在switch
中的break
,只是跳出switch
,并不会跳出while
,所以我们还需要一个标识符,判断是否要跳出while
循环
1 | while (true) |
这里我们添加一个bool变量类型的isQuitWhile
,默认为false
当玩家按下J
时,改变它的值,再在switch
的外面,while
循环内,
判断一下,如果为true
,则跳出循环
OK,那么第一个部分就写完了,下面是第一部分的完整代码
1 |
|
游戏场景
那么接下来,我们来讲游戏场景的代码
首先还是常规的,先清空控制台,因为我们切换到另外一个场景了,得把前一个场景的内容都清空
1 | Console.Clear(); |
接下来,我们一步步来实现上面的需求
绘制边界墙
在需求中,要求我们绘制边界墙,用红色的■
表示
那么边界墙,就是围着屏幕范围画一圈,可以用for循环来实现
1 | // 调整颜色 |
h是前面写到的屏幕高度,w是屏幕宽度
h-1是为了防止越界,i的步长为2,也是因为这个小方块占2个字符宽度
这里我们一共绘制3道横墙,第一道墙在屏幕顶部,第二道墙在距离屏幕底部上方5个字符处,
第三道墙在屏幕底部,在第二道和第三道墙之间是打印信息的区域
接下来是绘制竖墙,竖墙的绘制和横墙的绘制类似,只不过横墙是i+=2
,竖墙是i++
1 | // 两道竖墙 |
竖墙就第一列和最后一列要绘制
现在我们测试,进入游戏场景时,就可以看到红色的边界墙了
绘制玩家
那么边界墙已经绘制好了,接下来就是绘制玩家和Boss了
不过要注意的是,因为后面玩家要移动,还有攻击逻辑,所以我们要将它们放在循环中
我们先绘制玩家,玩家用黄色的●
表示,至于一开始玩家要生成的位置,我们可以直接指定一个位置
不过,如果你要高级一点的话则可以使用Random,来随机给定一个位置,这里我们就指定了
1 | while (true) |
这里我们定义了一个playerX
和playerY
,分别表示玩家在屏幕中的位置
再定义一个玩家的颜色,最后根据位置和颜色信息来绘制玩家,现在当我们进入第二个场景时,
就可以看到一个黄色小球了
不过,或许有人会问,为什么墙的绘制没有放在循环中,而是放在了循环外面呢?
因为墙的位置是固定的,不会改变,所以放在循环外面,
而玩家和Boss的位置和状态(当然在这里我们的Boss是不会动的,但是会死亡)是会改变的,
所以放在循环中
绘制Boss
那么玩家已经绘制好了,接下来就是绘制Boss了,也和玩家绘制差不多
Boss用绿色的■
表示,位置我们也指定一下好了
1 | int bossX = 24; |
随后我们就可以看到一个绿色的小方块
控制玩家移动
那么,接下来就来到游戏的循环层,要获取用户的输入,控制玩家移动
这个东西我们在上面已经写过了,所以这里我们就直接来写
1 | switch (input2) |
复杂数据类型
枚举
枚举是一种数据类型,用于定义一组命名常量
(其值为整型
),一般用来表示状态、类型等等
声明
枚举的声明
方式如下:
1 | enum 枚举名 |
枚举名可以加上E
以区分其他数据类型,具体使用:
1 | enum EColor |
枚举值从0
开始,也可以手动指定枚举值,后面的枚举值会在此基础上累加
使用示例
1 | // 声明枚举变量 |
类型转换
因为枚举类型中的枚举项实际上是整型常量
,所以枚举类型可以和整型进行转换,转换方式如下:
1 | // 枚举的类型转换(int) |
同样枚举也可以转换为string
类型
1 | // 枚举的类型转换(string) |
而string
类型也可以转换为枚举类型
其语法为
1 | 目标枚举类型 变量名 = (目标枚举类型)Enum.Parse(typeof(目标枚举类型), "枚举成员"); |
使用示例
1 | EColor color2 = (EColor)Enum.Parse(typeof(EColor), "GREEN"); |
数组
数组是一种数据类型,用于存储一组相同类型
的数据,其长度是固定的,不能改变
数组有一维数组、二维数组、多维数组、交错数组等等
一维数组
声明
一维数组的声明方式如下:
1 | 数据类型[] 数组名; |
数组长度获取
获取数组长度可以使用Length
属性
1 | int[] arr = { 1, 2, 3, 4, 5 }; |
数组元素访问、修改
数组元素可以通过索引来访问,索引从0
开始,但索引不得越界
(数组长度 - 1
)
1 | int[] arr = { 1, 2, 3, 4, 5 }; |
同样可以利用这种方法来修改数组元素
1 | int[] arr = { 1, 2, 3, 4, 5 }; |
数组遍历
数组遍历可以使用for
循环,也可以使用foreach
循环
1 | int[] arr = { 1, 2, 3, 4, 5 }; |
增加元素
由于数组初始化之后就不能再添加新元素,我们要使用搬家
的方法来实现
即重新定义一个更长
长度的数组,将原数组中的元素复制到新数组中,最后将新数组赋值给原数组
1 | int[] arr3 = { 1, 2, 3, 4, 5 }; |
删除元素
删除元素同样如此
1 | int[] arr3 = { 1, 2, 3, 4, 5 }; |
但其实在实际开发过程中,我们并不会这么干,后续会接触到更好的方法来处理数组
查找元素
查找元素可以使用for
循环遍历数组
1 | for (int i = 0; i < arr3.Length; i++) |
二维数组
声明
声明上与一维数组差不多,只不过需要多一个维度
1 | 数据类型[,] 数组名; |
数组长度获取
对于二维数组来说,GetLength()方法返回的是数组的总元素个数,而GetLength(0)和GetLength(1)分别返回的是数组的行数和列数
1 | int[,] arr = new int[3, 4]; |
数组元素访问、修改
二维数组可以通过行索引
和列索引
来访问、修改元素
1 | int[,] arr = new int[3, 4]; |
数组遍历
二维数组可以通过for
循环来遍历,但是因为有两个维度,需要嵌套两个for
循环
1 | int[,] arr = {{ 1, 2, 3 }, { 4, 5, 6 } }; |
增加元素
二维数组同样需要使用搬家
的方法来实现增加元素
1 | int[,] arr5 = new int[3, 3]; |
删除元素
1 | int [,] arr6 = new int[2, 2]; |
查找元素
1 | for (int i = 0; i < arr4.GetLength(0); i++) |
交错数组
交错数组是数组的数组,即二维数组中的每一行都是一个一维数组
声明
1 | 数据类型[][] 数组名; |
数组长度获取
GetLength(0)返回的是数组的行数,但列数要先获取某一行的值,再通过Length获取
1 | Console.WriteLine(jaggedArray4.GetLength(0)); // 行数 |
数组元素访问、修改
1 | // 获取元素 |
数组遍历
1 | for (int i = 0; i < jaggedArray4.GetLength(0); i++) |
后面的增删查都与前面的差不多,这里就不再赘述