C#基本语法整理-枚举&二维数组&ref&out&变长参数&结构体

375 阅读8分钟

一.引言

从此片章开始会整理C#中比较复杂并且常用的一些数据类型,给后续的Unity开发打扎实基础

二.枚举

  1. 枚举的概念
    枚举是一个被命名的整形常量的集合,一般用它来表示状态、类型等等
  2. 申明枚举和申明枚举变量,这是两个概念
    • 申明枚举:相当于是 创建一个自定义的枚举类型
    • 申明枚举变量:使用申明的自定义枚举类型 创建一个枚举变量
  3. 申明枚举语法
    // 枚举名 以E或者E_开头 作为我们的命名规范
    //enum E_自定义枚举名
    //{
    //    自定义枚举项名字, //枚举中包裹的 整形常量  第一个默认值是0 下面会依次累加
    //    自定义枚举项名字1,//1
    //    自定义枚举项名字2,//2
    //}
    
    //enum E_自定义枚举名
    //{
    //    自定义枚举项名字 = 5, //第一个枚举项的默认值 变成5了 
    //    自定义枚举项名字1,// 6
    //    自定义枚举项名字2 = 100,
    //    自定义枚举项名字3,//101
    //    自定义枚举项名字4,//102
    //}
    
  4. 在哪里申明枚举
    • namespace语句块中(常用)
    • class语句块中 struct语句块中 注意:枚举不能在函数语句块中申明!!!
    enum E_MonsterType
        {
            Normal,//0
    
            Boss,//1
        }
    
        enum E_PlayerType
        {
            Main,
            Other,
        }
    
  5. 枚举的使用

    自定义的枚举类型 变量名 = 默认值;(自定义的枚举类型.枚举项)

                E_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;
                }
    
    枚举搭配switch,tab键一按就会自动补全所有case
  6. 枚举的类型转换
    • 枚举和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#中不比其他语言,二维数组比较有特色,这里单独列出来,声明语法也大不相同

  1. 二维数组
    • 二维数组的申明
            //变量类型[,] 二维数组变量名;
            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
                }
            }
    

    所有的变量类型都可以申明为二维数组,游戏中一般用来存储 矩阵,再控制台小游戏中可以用二维数组 来表示地图格子

  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); //通常这样写,声明和使用放在一起

区别总结:

  1. ref传入的变量必须初始化 但是在内部 可改可不改
  2. out传入的变量不用初始化 但是在内部 必须修改该值(必须赋值)

五.变长参数和可选参数

两者在项目开发中用得也相对比较频繁,变长参数的语法和其他语言也不一样,另外再强调一下可选参数

  1. 变长参数
            //变长参数关键字 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)
          {
      
          }
          // 变长参数一定要放在最后
      
  2. 可选参数
    有参数默认值的参数 一般称为可选参数
    作用是 当调用函数时可以不传入参数,不传就会使用默认值作为参数的值
            static void Speak(string str = "我没什么话可说")
            {
                Console.WriteLine(str);
            }
    
    注意:
    • 支持多参数默认值 每个参数都可以有默认值
    • 如果要混用 可选参数 必须写在 普通参数后面
      static void Speak2(string a, string test, string name = "C#", string str = "我没什么话可说")
      {
      
      }
      

六.结构体

C语言里也有结构体,这里就简单梳理一下,可以将结构体理解为类的前身

  1. 基本概念
    结构体 是一种自定义变量类型 类似枚举需要自己定义
    它是数据和函数的集合
    在结构体中 可以申明各种变量和方法
    作用:用来表现存在关系的数据集合 比如用结构体表现学生 动物 人类等等
  2. 基本语法
        //1.结构体一般写在 namespace语句块中
        //2.结构体关键字 struct
    
        //struct 自定义结构体名
        //{
        //    // 第一部分
        //    // 变量
    
        //    // 第二部分
        //    // 构造函数(可选)
    
        //    // 第三部分 
        //    // 函数
        //}
        // 注意 结构体名字 我们的规范 是 帕斯卡命名法
    
  3. 构造以及访问修饰符
       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);
        }
        //可以根据需求 写无数个函数的
    }
    
  4. 结构体的使用
            //变量类型 变量名;
            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