一.引言
从此片章开始会整理C#中比较复杂并且常用的一些数据类型,给后续的Unity开发打扎实基础
二.枚举
- 枚举的概念
枚举是一个被命名的整形常量的集合,一般用它来表示状态、类型等等 - 申明枚举和申明枚举变量,这是两个概念
- 申明枚举:相当于是 创建一个自定义的枚举类型
- 申明枚举变量:使用申明的自定义枚举类型 创建一个枚举变量
- 申明枚举语法
// 枚举名 以E或者E_开头 作为我们的命名规范 //enum E_自定义枚举名 //{ // 自定义枚举项名字, //枚举中包裹的 整形常量 第一个默认值是0 下面会依次累加 // 自定义枚举项名字1,//1 // 自定义枚举项名字2,//2 //} //enum E_自定义枚举名 //{ // 自定义枚举项名字 = 5, //第一个枚举项的默认值 变成5了 // 自定义枚举项名字1,// 6 // 自定义枚举项名字2 = 100, // 自定义枚举项名字3,//101 // 自定义枚举项名字4,//102 //} - 在哪里申明枚举
- namespace语句块中(常用)
- class语句块中 struct语句块中 注意:枚举不能在函数语句块中申明!!!
enum E_MonsterType { Normal,//0 Boss,//1 } enum E_PlayerType { Main, Other, } - 枚举的使用
自定义的枚举类型 变量名 = 默认值;(自定义的枚举类型.枚举项)
枚举搭配switch,tab键一按就会自动补全所有caseE_PlayerType playerType = E_PlayerType.Other; if (playerType == E_PlayerType.Main) { Console.WriteLine("主玩家逻辑"); } else if (playerType == E_PlayerType.Other) { Console.WriteLine("其它玩家逻辑"); } //枚举和switch是天生一对 E_MonsterType monsterType = E_MonsterType.Boss; switch (monsterType) { case E_MonsterType.Normal: //Console.WriteLine("普通怪物逻辑"); //break; case E_MonsterType.Boss: Console.WriteLine("Boss逻辑"); break; default: break; } - 枚举的类型转换
- 枚举和int互转
int i = (int)playerType; Console.WriteLine(i); //int 转枚举 playerType = 0; // 强转方式 E_PlayerType int2Enum = (E_PlayerType)0;- 枚举和string相互转换
string str = playerType.ToString(); Console.WriteLine(str); //把string转成枚举呢 //Parse后 第一个参数 :你要转为的是哪个 枚举类型 第二个参数:用于转换的对应枚举项的字符串 //转换完毕后 是一个通用的类型 我们需要用括号强转成我们想要的目标枚举类型 playerType = (E_PlayerType)Enum.Parse(typeof(E_PlayerType), "Other"); Console.WriteLine(playerType);在游戏开发中,对象很多时候会有许多的状态,枚举可以帮助我们 清晰的分清楚状态的含义
三.二维数组与交错数组
C#中不比其他语言,二维数组比较有特色,这里单独列出来,声明语法也大不相同
- 二维数组
- 二维数组的申明
//变量类型[,] 二维数组变量名; int[,] arr; //申明过后 会在后面进行初始化 //变量类型[,] 二维数组变量名 = new 变量类型[行,列]; int[,] arr2 = new int[3, 3]; //变量类型[,] 二维数组变量名 = new 变量类型[行,列]{ {0行内容1, 0行内容2, 0行内容3.......}, {1行内容1, 1行内容2, 1行内容3.......}.... }; int[,] arr3 = new int[3, 3] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; //变量类型[,] 二维数组变量名 = new 变量类型[,]{ {0行内容1, 0行内容2, 0行内容3.......}, {1行内容1, 1行内容2, 1行内容3.......}.... }; int[,] arr4 = new int[,] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; //变量类型[,] 二维数组变量名 = { {0行内容1, 0行内容2, 0行内容3.......}, {1行内容1, 1行内容2, 1行内容3.......}.... }; int[,] arr5 = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };- 二维数组的使用
int[,] array = new int[,] { { 1, 2, 3 }, { 4, 5, 6 } }; //1.二维数组的长度 //我们要获取 行和列分别是多长 //得到多少行 Console.WriteLine(array.GetLength(0)); //得到多少列 Console.WriteLine(array.GetLength(1)); //2.获取二维数组中的元素 // 注意:第一个元素的索引是0 最后一个元素的索引 肯定是长度-1 Console.WriteLine(array[0, 1]); Console.WriteLine(array[1, 2]); //3.修改二维数组中的元素 array[0, 0] = 99; Console.WriteLine(array[0, 0]); Console.WriteLine("**********"); //4.遍历二维数组 for (int i = 0; i < array.GetLength(0); i++) { for (int j = 0; j < array.GetLength(1); j++) { //i 行 0 1 //j 列 0 1 2 Console.WriteLine(array[i, j]); //0,0 0,1 0,2 //1,0 1,1 1,2 } }所有的变量类型都可以申明为二维数组,游戏中一般用来存储 矩阵,再控制台小游戏中可以用二维数组 来表示地图格子
- 交错数组
交错数组的声明方式更像其他语言那样,平时用的比较少,非重点,了解即可
交错数组是数组的数组,每个维度的数量可以不同- 交错数组的声明
//变量类型[][] 交错数组名; int[][] arr1; //变量类型[][] 交错数组名 = new 变量类型[行数][]; int[][] arr2 = new int[3][]; //变量类型[][] 交错数组名 = new 变量类型[行数][]{ 一维数组1, 一维数组2,........ }; int[][] arr3 = new int[3][] { new int[] { 1, 2, 3 }, new int[] { 1, 2 }, new int[] { 1 }}; //变量类型[][] 交错数组名 = new 变量类型[][]{ 一维数组1, 一维数组2,........ }; int[][] arr4 = new int[][] { new int[] { 1, 2, 3 }, new int[] { 1, 2 }, new int[] { 1 }}; //变量类型[][] 交错数组名 = { 一维数组1, 一维数组2,........ }; int[][] arr5 = { new int[] { 1, 2, 3 }, new int[] { 1, 2 }, new int[] { 1 }};- 交错数组的使用
int[][] array = { new int[] { 1,2,3}, new int[] { 4,5} }; //1.数组的长度 //行 Console.WriteLine(array.GetLength(0)); //得到某一行的列数 Console.WriteLine(array[0].Length); //2.获取交错数组中的元素 // 注意:不要越界 Console.WriteLine(array[0][1]); //3.修改交错数组中的元素 array[0][1] = 99; Console.WriteLine(array[0][1]); //4.遍历交错数组 for (int i = 0; i < array.GetLength(0); i++) { for (int j = 0; j < array[i].Length; j++) { Console.Write(array[i][j] + " "); } Console.WriteLine(); }
四.ref&out关键字
ref和out的功能是一样的,解决值类型和引用类型 在函数内部 改值 或者 重新申明 能够影响外部传入的变量 让其也被修改,简单说就是传入的是C语言中的引用或者指针 两者的区别如下:
//ref
static void ChangeValueRef(ref int value)
{
//out传入的变量必须在内部赋值 ref不用
value = 3;
}
//out
static void ChangeValueOut(out int value)
{
//out传入的变量必须在内部赋值 ref不用
value = 99;
}
// 使用
// ref
int a = 10;
ChangeValueRef(ref a);
// out
ChangeValueOut(out int b); //通常这样写,声明和使用放在一起
区别总结:
- ref传入的变量必须初始化 但是在内部 可改可不改
- out传入的变量不用初始化 但是在内部 必须修改该值(必须赋值)
五.变长参数和可选参数
两者在项目开发中用得也相对比较频繁,变长参数的语法和其他语言也不一样,另外再强调一下可选参数
- 变长参数
注意://变长参数关键字 params static int Sum(params int[] arr) { int sum = 0; for (int i = 0; i < arr.Length; i++) { sum += arr[i]; } return sum; } //params int[] 意味着可以传入n个int参数 n可以等于0 传入的参数会存在arr数组中- params关键字后面必为数组
- 数组的类型可以是任意的类型
- 函数参数可以有 别的参数和 params关键字修饰的参数
- 函数参数中只能最多出现一个params关键字 并且一定是在最后一组参数 前面可以有n个其它参数
static void Eat(string name, int a, int b, params string[] things) { } // 变长参数一定要放在最后
- 可选参数
有参数默认值的参数 一般称为可选参数
作用是 当调用函数时可以不传入参数,不传就会使用默认值作为参数的值注意:static void Speak(string str = "我没什么话可说") { Console.WriteLine(str); }- 支持多参数默认值 每个参数都可以有默认值
- 如果要混用 可选参数 必须写在 普通参数后面
static void Speak2(string a, string test, string name = "C#", string str = "我没什么话可说") { }
六.结构体
C语言里也有结构体,这里就简单梳理一下,可以将结构体理解为类的前身
- 基本概念
结构体 是一种自定义变量类型 类似枚举需要自己定义
它是数据和函数的集合
在结构体中 可以申明各种变量和方法
作用:用来表现存在关系的数据集合 比如用结构体表现学生 动物 人类等等 - 基本语法
//1.结构体一般写在 namespace语句块中 //2.结构体关键字 struct //struct 自定义结构体名 //{ // // 第一部分 // // 变量 // // 第二部分 // // 构造函数(可选) // // 第三部分 // // 函数 //} // 注意 结构体名字 我们的规范 是 帕斯卡命名法 - 构造以及访问修饰符
struct Student { #region 知识点五 访问修饰符 //修饰结构体中变量和方法 是否能被外部使用 //public 公共的 可以被外部访问 //private 私有的 只能在内容使用 //默认不写 为private #endregion //变量 //结构体申明的变量 不能直接初始化 //变量类型 可以写任意类型 包括结构体 但是 不能是自己的结构体 可以是其它的 //Student s;// 不能是自己的结构体 //年龄 public int age; //性别 public bool sex; //学号 public int number; //姓名 public string name; //构造函数 #region 知识点六 结构体的构造函数 //基本概念 //1.没有返回值 //2.函数名必须和结构体名相同 //3.必须有参数 //4.如果申明了构造函数 那么必须在其中对所有变量数据初始化 //构造函数 一般是用于在外部方便初始化的 public Student(int age, bool sex, int number, string name) { //新的关键字 this //代表自己 this.age = age; this.sex = sex; this.number = number; this.name = name; } #endregion //函数方法 //表现这个数据结构的行为 //注意 在结构体中的方法 目前不需要加static关键字 public void Speak() { //函数中可以直接使用结构体内部申明的变量 Console.WriteLine("我的名字是{0},我今年{1}岁", name, age); } //可以根据需求 写无数个函数的 } - 结构体的使用
//变量类型 变量名;
Student s1;
s1.age = 10;
s1.sex = false;
s1.number = 1;
s1.name = "C#";
s1.Speak();
Student s2 = new Student(18, true, 2, "小红");
s2.Speak();
注意:
- 在结构体中申明的变量 不能初始化 只能在外部或者在函数中赋值(初始化)
- 在结构体中申明的函数 不用加static