1.数组

1.1 定义

  • 数组是相同类型数据的有序集合
  • 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
  • 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们

1.2 声明创建

  • 首先必须声明数组变量,才能在程序中使用数组,下面是声明数组变量的语法:
  1. dataType[] arrayRefVar;
  2. 例:
  3. int[] intArray;
  • java语言使用new操作符来创建数组,语法如下:
  1. dataType[] arrayRefVar = new dataType[arraySize];
  2. 例:
  3. int[] intArray = new int[10];
  4. //创建一个数组,这里可以存放10个int类型的数字
  • 数组的元素是通过索引访问的,数组索引从0开始
  • 获取数组的长度:arrays.length
  • 数组编程示例:
  1. //1、声明一个数组
  2. int[] nums;
  3. //2、创建一个数组,这里可以存放10个int类型的数字
  4. nums = new int[10];
  5. //3、给数组元素中赋值
  6. nums[0] = 1;
  7. nums[1] = 2;
  8. nums[2] = 3;
  9. nums[3] = 4;
  10. nums[4] = 5;
  11. nums[5] = 6;
  12. nums[6] = 7;
  13. nums[7] = 8;
  14. nums[8] = 9;
  15. nums[9] = 10;
  16. //计算所有元素的和
  17. int sum = 0;
  18. //获取数组长度:arrays.length
  19. for (int i = 0; i < nums.length; i++) {
  20. sum = sum + nums[i];
  21. }
  22. Console.WriteLine("总和为:"+sum);

1.3 数组的三种初始化

  1. 静态初始化
  1. int[] a = {1,2,3};
  1. 动态初始化(包含3.默认初始化)
  1. int[] a = new int[2];
  2. a[0]=1;
  3. a[1]=2;
  1. 数组的默认初始化
    • 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化

1.4 数组的四个基本特点

  • 其长度是确定的。数组一旦被创建,它的大小就是不可改变的
  • 其元素必须是相同类型,不允许出现混合类型。
  • 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
  • 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。

1.5 数组边界

  • 下标的合法区间:[0,length-1],如果越界就会报错;
  1. int[] a= new int[2];
  2. Console.WriteLine(a[2]);
  • IndexOutOfRangeException:数组下标越界异常!
  • 小结:
    • 数组是相同数据类型(数据类型可以为任意类型)的有序集合
    • 数组也是对象,数组元素相当于对象的成员变量
    • 数组长度是确定的,不可变的。如果越界,则报异IndexOutOfRangeException

1.6 数组的使用

  • 普通的For循环
  • For-Each循环
  • 数组作为方法入参
  • 数组作返回值
  • 示例1:
  1. int [] arrays = {1,2,3,4,5};
  2. //打印全部的数组元素
  3. for (int i = 0; i < arrays.Length; i++) {
  4. Console.WriteLine(arrays[i]);
  5. }
  6. Console.WriteLine("=======================================");
  7. //计算所有元素的和
  8. int sum = 0;
  9. for (int i = 0; i < arrays.Length; i++) {
  10. sum += arrays[i];
  11. }
  12. Console.WriteLine("sum=" + sum);
  13. Console.WriteLine("=======================================");
  14. //查找最大元素
  15. int max = arrays[0];
  16. for (int j = 1; j < arrays.Length; j++) {
  17. if (arrays[j]>max){
  18. max = arrays[j];
  19. }
  20. }
  21. Console.WriteLine("max=" + max);
  • 示例2(把示例1改为foreach用法):
  1. int [] arrays = {1,2,3,4,5};
  2. //打印全部的数组元素
  3. foreach (int i in arrays) {
  4. //foreach相当于每次把arrays中的值赋值给i,所以每次要调用i,而不是arrays[i]
  5. Console.WriteLine(i);
  6. }
  7. Console.WriteLine("=======================================");
  8. //计算所有元素的和
  9. int sum = 0;
  10. foreach (int i in arrays) {
  11. sum += i;
  12. }
  13. Console.WriteLine("sum=" + sum);
  14. Console.WriteLine("=======================================");
  15. //查找最大元素
  16. int max = arrays[0];
  17. foreach (int i in arrays) {
  18. if (i > max){
  19. max = i;
  20. }
  21. }
  22. Console.WriteLine("max=" + max);

2.多维数组

2.1 定义

  1. 多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。

2.2 声明

  1. int[,] a = new int[2][5];
  • 解析:以上二维数组a可以看成一个两行五列的数组
  • 思考:多维数组的使用?
    num [1] [0]

2.3 编码举例

  1. //[4,2]
  2. /*
  3. 1,2 array[0]
  4. 2,3 array[1]
  5. 3,4 array[2]
  6. 4,5 array[3]
  7. */
  8. int[,] array = { { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 5 } };
  9. //打印多维数组的第一维长度(行数)
  10. Console.WriteLine("行数:" + array.GetLength(0));
  11. //打印多维数组的第二维长度(列数)
  12. Console.WriteLine("列数:" + array.GetLength(1));
  13. //打印第一行第一列的数字
  14. Console.WriteLine("[0,0]位置数字:" + array[0,0]);
  15. //打印多维数组的所有元素
  16. for (int i = 0; i < array.GetLength(0); i++)
  17. {
  18. for (int j = 0; j < array.GetLength(1); j++)
  19. {
  20. Console.WriteLine(array[i,j]);
  21. }
  22. }

2.4 C#对比java

2.4.1 声明
  1. //java
  2. int[][] a = new int[1][1];
  3. //C#
  4. int[,] a = new int[1][1];

2.4.2 获取行列数
  1. //java
  2. //获取行数
  3. System.out.println(array.length);
  4. //获取列数
  5. System.out.println(array[0].length);
  6. //C#
  7. //获取行数
  8. Console.WriteLine(array.GetLength(0));
  9. //获取列数
  10. Console.WriteLine(array.GetLength(1));

2.4.3 访问元素
  1. //java
  2. System.out.println(array[0][0]);
  3. //C#
  4. Console.WriteLine(array[0,0]);

3.字符串(String)

3.1 定义

在 C# 中,您可以使用字符数组来表示字符串,但是,更常见的做法是使用 string 关键字来声明一个字符串变量。string 关键字是 System.String 类的别名。

3.2 如何创建String对象

您可以使用以下方法之一来创建 string 对象:

  • 通过给 String 变量指定一个字符串
  • 通过使用 String 类构造函数
  • 通过使用字符串串联运算符( + )
  • 通过检索属性或调用一个返回字符串的方法
  • 通过格式化方法来转换一个值或对象为它的字符串表示形式

3.3 实例与功能

3.3.1 字符串拼接
  1. //字符串初始化
  2. string fname, lname;
  3. fname = "Fudo";
  4. lname = "Yusei";
  5. //字符串拼接
  6. string fullname = fname + lname;
  7. //输出字符串
  8. Console.WriteLine("Full Name: {0}", fullname);

结果输出:

  1. Full Name: FudoYusei

3.3.2 通过string构造函数转化char数组
  1. //字符数组初始化
  2. char[] cArray = { 'g','o','o','d' };
  3. //使用字符数组创建字符串
  4. string s = new string(cArray);
  5. //可以将char数组转化为string数组输出
  6. Console.WriteLine(s);

结果输出:

  1. good

3.3.3 使用join方法拼接字符串
  1. //字符串数组
  2. string[] sArray = { "Hello", "world" };
  3. //新建字符串并将字符串数组中的字符串进行拼接
  4. string message = String.Join(" ", sArray);
  5. //输出拼接好的字符串
  6. Console.WriteLine("Message: {0}", message);

结果输出:

  1. Message: Hello World

3.3.4 把字符串当成字符数组使用

字符串是一串字符,在程序中,一个字符串可以当做一个字符数组。

  1. //创建字符串
  2. string s = "string is a pig";
  3. //获取字符串长度
  4. Console.WriteLine(s.Length);
  5. //获取第i个字符
  6. Console.WriteLine(s[i-1]);

3.4 字符串常用方法

3.4.1 ToLower() 与 ToUpper()

ToLower() 与 ToUpper()能将字符串转为小写或者转为大写,使用这两个方法会生成新字符串,不会影响原有字符串

  1. //创建字符串
  2. string s = "FudoYusei";
  3. //字符串转小写
  4. Console.WriteLine(s.ToLower());
  5. //字符串转大写
  6. Console.WriteLine(s.ToUpper());

输出结果:

  1. fudoyusei
  2. FUDOYUSEI

3.4.2 Trim() 、TrimStart() 、TrimEnd()

Trim()系列方法可以将字符串中的空格去掉,且不会影响原有字符串

  1. //创建一个前中后都有空格的字符串
  2. string s = " Hello World ";
  3. //输出原字符串
  4. Console.WriteLine("|" + s + "|");
  5. //去除前后的空格
  6. Console.WriteLine("|" + s.Trim() + "|");
  7. //只去除前面的空格
  8. Console.WriteLine("|" + s.TrimStart() + "|");
  9. //只去除后面的空格
  10. Console.WriteLine("|" + s.TrimEnd() + "|");

输出结果:

  1. | Hello World |
  2. |Hello World|
  3. |Hello World |
  4. | Hello World|

3.4.3 Split()

Split()方法,可以将用特殊符号分割的字符串按特殊符号分割成几段字符串并存放到字符串数组中。

  1. //创建一个用‘,’分割的字符串
  2. string s = "zhangsan,lisi,wangwu";
  3. //将字符串分割且存放在字符串数组中
  4. string[] sArray = s.Split(",");
  5. //遍历输出字符串数组
  6. foreach(string i in sArray)
  7. {
  8. Console.WriteLine(i);
  9. }

输出结果:

  1. zhangsan
  2. lisi
  3. wangwu

3.4.4 ToCharArray()

由于字符串无法修改,修改字符串中的字符时,需要转换为字符数组进行修改。

  1. //创建一串字符串
  2. string str = "Hello World";
  3. //将字符串转化为字符数组
  4. char[] strArray = str.ToCharArray();
  5. //修改字符数组中的字符
  6. strArray[3] = 'a';
  7. //生成新字符串
  8. string str1 = new string(strArray);
  9. Console.WriteLine(str1);

输出结果:

  1. Helao World

4. 方法(Function 方法Method)

4.1 出现

方法的出现是为了解决以下需求:

  1. 如果需要重复执行某段代码,那就需要写重复的代码。
  2. 重复的代码多了,不容易管理且不容易维护。

例:某段代码的功能是校验用户输入的用户名是否符合要求,但如果程序中有多个地方需要校验,需要重复写校验,就会有重复代码。

而方法就相当于把重复的事情单独写在一块,每次当你需要用到的时候,直接就可以使用简单的语句并且调用,这样的写法更方便阅读以及修改,降低耦合度。

4.2 定义

4.2.1 C#中方法的定义句法
  1. 修饰符 返回值 方法名(参数列表)
  2. {
  3. 方法主体
  4. }

4.2.2 各个元素代表含义
  • Access Specifier:访问修饰符,这个决定了变量或方法对于另一个类的可见性。
  • Return type:返回类型,一个方法可以返回一个值。返回类型是方法返回的值的数据类型。如果方法不返回任何值,则返回类型为 void
  • Method name:方法名称,是一个唯一的标识符,且是大小写敏感的。它不能与类中声明的其他标识符相同。
  • Parameter list:参数列表,使用圆括号括起来,该参数是用来传递和接收方法的数据。参数列表是指方法的参数类型、顺序和数量。参数是可选的,也就是说,一个方法可能不包含参数。
  • Method body:方法主体,包含了完成任务所需的指令集。

4.2.3 例子
  1. public int FindMax(int num1, int num2)
  2. {
  3. /* 局部变量声明 */
  4. int result;
  5. if (num1 > num2)
  6. result = num1;
  7. else
  8. result = num2;
  9. return result;
  10. }

4.3 方法调用

4.3.1 方法调用句法
  1. 对象名.方法名(实参列表);

4.3.2 例子
  1. using System;
  2. namespace CalculatorApplication
  3. {
  4. class NumberManipulator
  5. {
  6. public int FindMax(int num1, int num2)
  7. {
  8. /* 局部变量声明 */
  9. int result;
  10. if (num1 > num2)
  11. result = num1;
  12. else
  13. result = num2;
  14. return result;
  15. }
  16. }
  17. class Test
  18. {
  19. static void Main(string[] args)
  20. {
  21. /* 局部变量定义 */
  22. int a = 100;
  23. int b = 200;
  24. int ret;
  25. NumberManipulator n = new NumberManipulator();
  26. //调用 FindMax 方法
  27. ret = n.FindMax(a, b);
  28. Console.WriteLine("最大值是: {0}", ret );
  29. Console.ReadLine();
  30. }
  31. }
  32. }

输出结果:

  1. 200

4.4 方法重载

4.4.1 定义

重载就是在一个类中,有相同的函数名称,但形参不同的函数

例:

假设我们有一个函数用来实现求得一个数组的最大值

  1. static int MaxValue(int[] intArray)
  2. {
  3. return;
  4. }

这个函数注能用于处理int数组,如果想处理double类型的话需要重新定义一个函数

  1. static double MaxValue(double[] doubleArray)
  2. {
  3. return;
  4. }

函数名相同,参数不同,这个叫做函数重载(编译器通过不同参数去识别应该使用哪一个函数)

4.4.2 规则

方法的重载的规则:

  • 方法名称必须相同
  • 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)
  • 方法的返回类型可以相同也可以不同
  • 仅仅返回类型不同不足以成为方法的重载

4.4.3 实现理论

方法名称相同时,编译器会根据调用方法的参数个数,参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。

5. 枚举类型

5.1 出现

枚举类型是一种自定义的类型

开发一个游戏,游戏角色有法师(Mage)、射手(Archer)、刺客(Assassin)、坦克(Tank)、辅助(Support)、战士(Warrior)等不同类型。

此时如何存储游戏的角色?

  1. 使用int类型(使用数字替代职业)
  1. static void Main(String[] args)
  2. {
  3. //1法师(Mage)、2射手(Archer)、3刺客(Assassin)、4坦克(Tank)、5辅助(Support)、6战士(Warrior)
  4. int roleType = 4;
  5. //若需要修改职业
  6. roleType = 3;
  7. }
  1. 使用枚举

5.2 声明

句法

  1. enum 枚举类型名
  2. {
  3. 1;
  4. 2;
  5. 3;
  6. ...
  7. n;
  8. }; //注意分号

例:

  1. enum RoleType
  2. {
  3. Mage,Archer,Assassin,Tank,Support,Warrior
  4. };

5.3 使用

若要使用5.2中的句子,则

  1. //使用刺客职业
  2. RoleType roleType = RoleType.Assassin;
  3. //判断是否为刺客职业
  4. if(roleTpye == RoleType.Archer)
  5. {
  6. 刺客专有技能
  7. }

6. 结构体

目前所知变量,都是单一的信息,比如

age

name

grade

studyID

对于一个学生信息的话,是包含这些的,我们怎么对这些信息进行一个整合呢?

这时候就要用到结构体。

结构体的作用是把某一类的变量进行整合,组成一个新的数据类型,相当于一个新的信息。

比如:学生信息(包含 年龄,姓名,年级,学号)

6.1 定义

  1. struct 结构体名
  2. {
  3. 访问权限 类型1 变量名1;
  4. 访问权限 类型2 变量名2;
  5. ...
  6. 访问权限 类型n 变量名n;
  7. }

例:

  1. struct StudentInfo
  2. {
  3. public int age;
  4. public string name;
  5. public int grade;
  6. public string studyID;
  7. }

6.2 声明

  1. 结构体名 结构体个体名;

例:

  1. StudentInfo student1;
  2. StudentInfo student2;
  3. student1.age = 10; //赋值
  4. student1.name = "小明";
  5. student2.age = 12;

6.3 结构体函数

假设某个结构体需要用到方法,且这个方法专门为这个结构体服务,则可以将函数定义在结构体内。

例:

需要打印某个坐标xyz轴。

  1. struct Position
  2. {
  3. public double x;
  4. public double y;
  5. public double z;
  6. public void Printposition(){
  7. Conlsole.WriteLine(x + "," + y + "," + z);
  8. }
  9. }
  10. //初始化及赋值
  11. Position p1;
  12. p1.x = 23.1;
  13. p1.y = 2.1;
  14. p1.z = 2.3;
  15. //调用函数
  16. p1.PrintPosition();

7. 委托

C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。

委托(Delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生自 System.Delegate 类。

简单来说,委托就是一个方法选择器,当你想使用哪个方法时,就把哪个方法交给委托,然后通过委托来完成

注意:使用时委托的返回值和参数类型要与目标函数相同。

7.1 出现

当两个程序员同时开发某个游戏时,A程序员在做主角模块,程序员B在做死亡模块,而程序员A并不知道程序员B写的死亡模块的内容,同时程序员A想调用程序员B的模块,这时候需要用到委托。

  1. //程序员A 主角模块
  2. delegate void OnDieDelegate();//声明委托
  3. static void Play(OnDieDelegate onDie)//预留一个委托给程序员B,若想调用则将程序员B的死亡模块函数赋值给委托
  4. {
  5. Console.WriteLine("做任务");
  6. Console.WriteLine("玩家战斗");
  7. Console.WriteLine("死亡");
  8. if(onDie != null)//若不想调用,则可以传null
  9. {
  10. onDie();//调用委托,而内容因委托而定,比如程序员B写的内容
  11. }
  12. }
  13. //程序员B 死亡模块
  14. static void ShowDieUI()
  15. {
  16. Console.WriteLine("显示游戏死亡后的UI");
  17. Console.WriteLine("返回首页UI");
  18. }
  19. //主函数
  20. static void Main(string[] args)
  21. {
  22. // A主角
  23. // BUI菜单
  24. //Play(null);//不调用模块
  25. Play(ShowDieUI);//调用死亡模块
  26. }

7.2 声明

  1. delegate 返回值 委托名 (委托参数);

例如有一个乘法函数:

  1. public double Multiply(double param1 ,double param2)
  2. {
  3. return param1 * param2;
  4. }

想对此函数创建一个适合这个函数的委托:

  1. delegate double MyDelegate(double param1 ,double param2);

7.3 实例化

对7.1声明进行实例化且赋值:

  1. MyDelegate delegatel;
  2. //赋值
  3. delegatel = Multiply;

7.4 调用

  1. Console.WriteLine(delegate1(2,4));