经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C# » 查看文章
C#学习笔记--复杂数据类型、函数和结构体
来源:cnblogs  作者:畅知  时间:2023/10/13 8:42:19  对本文有异议

C#基础

复杂数据类型

特点:多个数据变量地一个集合体,可以自己命名

种类:枚举、数组和结构体

  • 枚举:整型常量的集合
  • 数组:任意变量类型的顺序存储的数据集合
  • 结构体:任意变量类型的数据组合成的数据块

枚举

枚举可以方便表示对象的各种状态,本质还是一种变量。

例如我们可以用枚举来表示怪物的种类、玩家的动作状态(静止、战斗、受伤......)

枚举的声明:

  1. enum E_MonsterType//命名E_XXX
  2. {
  3. Normal,//0
  4. Boss,//1 自动根据上一个数值顺延
  5. }
  6. enum E_PlayerType
  7. {
  8. Main,
  9. Other,
  10. }

枚举类型的使用:

  1. //自定义的枚举类型 变量名 = 默认值;(自定义的枚举类型.枚举项)
  2. E_PlayerType playerType = E_PlayerType.Other;
  3. if( playerType == E_PlayerType.Main )
  4. {
  5. Console.WriteLine("主玩家逻辑");
  6. }
  7. else if(playerType == E_PlayerType.Other)
  8. {
  9. Console.WriteLine("其它玩家逻辑");
  10. }
  11. //枚举也常常与switch语句做配合
  12. //枚举和switch是天生一对
  13. E_MonsterType monsterType = E_MonsterType.Boss;
  14. switch (monsterType)
  15. {
  16. case E_MonsterType.Normal:
  17. Console.WriteLine("普通怪物逻辑");
  18. break;
  19. case E_MonsterType.Boss:
  20. Console.WriteLine("Boss逻辑");
  21. break;
  22. default:
  23. break;
  24. }

枚举类型转换:

  • 枚举与int互转:
  1. int i=(int) playerType;
  2. playerType=0;
  • 枚举与string互转:
  1. playerType=(E_PlayerType)Enum.Paese(typeof(E_PlayerType),"other");
  2. string str=playerType.ToSring();

数组

数组是存储同一种特定变量类型的有序数据集合,内存上的连续存储。

一维数组

  1. //数组声明
  2. int[] arr1;//未分配内存地址
  3. int[] arr2=new int[5];//元素默认值0
  4. int[] arr3=new int[5]{1,2,3,4,5};
  5. int[] arr4=new int[]{1,2,3};
  6. int[] arr5={1,2,3,4,5,6};
  7. //数组的使用
  8. arr2.Length;//长度
  9. arr2[0];//获取数组中的元素
  10. arr2[2]=99;//修改内容
  11. //数组的遍历
  12. for(int i=0;i<arr2.Length;i++)
  13. {
  14. //遍历
  15. Console.WriteLine(arr2[i]);
  16. }
  17. //数组的自定义扩容
  18. //声明新的大容量数组,把旧有的进行复制转移
  19. int[] array2 = new int[6];
  20. //搬家
  21. for (int i = 0; i < array.Length; i++)
  22. {
  23. array2[i] = array[i];
  24. }
  25. array = array2;
  26. //自定义实现数组的删除元素
  27. int[] array3 = new int[5];
  28. //搬家 转移
  29. for (int i = 0; i < array3.Length; i++)
  30. {
  31. array3[i] = array[i];
  32. }
  33. array = array3;
  34. //查找数组中元素
  35. //只有遍历数组 找到合适的则终止遍历
  36. int a = 3;
  37. for (int i = 0; i < array.Length; i++)
  38. {
  39. if( a == array[i] )
  40. {
  41. Console.WriteLine("和a相等的元素在{0}索引位置", i);
  42. break;
  43. }
  44. }

多维数组(二维数组)

  1. //二维数组
  2. //声明
  3. int[,] arr;
  4. int[,] arr2=new int[3,4];
  5. int[,] arr3=new int[3,4]{{0,1,2,3},//给元素内容 告诉维度 元素个数
  6. {0,1,2,3},
  7. {0,1,2,3}};
  8. int[,] arr4=new int[,]{{0,1,2,3},//给元素内容 告诉维度
  9. {0,1,2,3},
  10. {0,1,2,3}};
  11. int[,] arr5={{0,1,2,3}, //直接给元素内容
  12. {0,1,2,3},
  13. {0,1,2,3}};
  14. //使用
  15. //获取长度
  16. arr3.GetLength(0);//行的长度
  17. arr3.GetLength(1);//列的长度
  18. //获取元素
  19. arr3[1,1];//第一行第一列的元素
  20. //遍历二维数组
  21. for(int i=0;i<arr3.GetLength(0);i++)
  22. {
  23. for(int j=0;j<arr3.GetLength(1);j++)
  24. {
  25. //访问 具体元素
  26. }
  27. }
  28. //增加数组元素
  29. //思想:新建一个大容量的数组,将小的数组元素复制到大的数组中
  30. //最后修改小的数组索引指向大的数组 实现“数组扩容”
  31. //删除数组元素(同增加)
  32. //查找数组中的元素(遍历比对)

交错数组

交错数组区别于多维数组,是数组的数组,一维数组元素也是数组,且长度不必完全相同。

  1. //交错数组
  2. //声明
  3. int [][] arr1;
  4. int [][] arr2=new int[3][];//不可以规定列的长度
  5. int [][] arr3=new int[3][]{
  6. new int[] {1,2,3,4},
  7. new int[] {1,2,3},
  8. new int[] {1}
  9. };//体会数组的数组的含义!
  10. int [][] arr4=new int[][]{
  11. new int[] {1,2,3,4},
  12. new int[] {1,2,3},
  13. new int[] {1}
  14. };
  15. int [][] arr5={//也可以直接赋值
  16. new int[] {1,2,3,4},
  17. new int[] {1,2,3},
  18. new int[] {1}
  19. };
  20. //数组的使用
  21. //长度
  22. arr3.GetLength(0);//行数
  23. arr3[0].Length;//第0行的长度
  24. //获取元素
  25. arr3[0][2];
  26. //遍历
  27. for(int i=0;i<arr3.GetLength(0);i++)
  28. {
  29. for(int j=0;j<arr3[i].Legth;j++)
  30. {
  31. //访问元素
  32. Console.WriteLine(arr3[i][j]);
  33. }
  34. }

值类型和引用类型

值类型的数值存储在(系统分配,自动回收GC,小而快)中、引用类型的存储在(大而慢,需手动分配与回收)中,栈中只存储其指针;

值类型在赋值时候将数值拷贝,而引用赋值修改引用指向的内存位置。

值类型:(14+2(枚举、结构体))

  • 无符号整型:byte ushort uint ulong
  • 有符号整型:sbyte short int long
  • 浮点数: float double decimal
  • 特殊类型:bool char
  • 结构体
  • 枚举:enum

引用类型:(5种)

string 、数组、类、接口、委托

函数

函数本质是封装的代码块,提升代码的复用率,抽象出具体的执行过程。

函数只能存在 structclass

  1. //函数出现在stuct与class中
  2. //函数种类
  3. //1 无参数 无返回值
  4. void sayHellow()
  5. {
  6. Console.WriteLine("Hello World");
  7. }
  8. //2 有参数 无返回值
  9. void sayHellow(string name)
  10. {
  11. Console.WriteLine("Hello,"+name);
  12. }
  13. //3 有参数 有返回值
  14. int Add(int a,int b)
  15. {
  16. return a+b;
  17. }
  18. //4 无参数 有返回值
  19. string getMyName()
  20. {
  21. return "TonyChang";
  22. }

ref 和 out

使用其可以解决在函数内部改变函数外部的变量的数值的问题。

(本质是传参数过程中传的是数值或引用是否完全绑定到同一个数值/内存空间中)

  1. //ref的使用
  2. using System;
  3. namespace CSharpLearn1
  4. {
  5. class Program
  6. {
  7. static void ChangeValue(int value)
  8. {
  9. value = 3;
  10. }
  11. static void ChangeArrayValue(int[] arr)
  12. {
  13. arr[0] = 33;
  14. }
  15. static void ChangeArray(int[] arr)
  16. {
  17. arr = new int[] {666,777,888,999 };
  18. }
  19. static void ChangeValueRef(ref int value)
  20. {
  21. value = 3;
  22. }
  23. static void ChangeArrayValueRef(ref int[] arr)
  24. {
  25. arr[0] = 33;
  26. }
  27. static void ChangeArrayRef( ref int[] arr)
  28. {
  29. arr = new int[] { 666, 777, 888, 999 };
  30. }
  31. static void Main(string[] args)
  32. {
  33. int a1 = 1;
  34. Console.WriteLine("a1原数值{0}", a1);
  35. ChangeValue(a1);
  36. Console.WriteLine("调用ChangValue函数之后a1的数值{0}", a1);//未改变数值
  37. ChangeValueRef(ref a1);
  38. Console.WriteLine("a1调用ChangValueRef函数之后a1的数值{0}", a1);//改变数值
  39. Console.WriteLine("********************************");
  40. int[] arr1 = { 100, 200, 300 };
  41. Console.WriteLine("arr1[0]原数值{0}", arr1[0]);
  42. ChangeArrayValue(arr1);
  43. Console.WriteLine("调用ChangArrayValue函数之后arr1[0]的数值{0}", arr1[0]);//改变数值
  44. Console.WriteLine("********************************");
  45. int[] arr2 = { 100, 200, 300 };
  46. Console.WriteLine("arr2[0]原数值{0}", arr2[0]);
  47. ChangeArray(arr2);
  48. Console.WriteLine("调用ChangArrayValue函数之后arr2[0]的数值{0}", arr2[0]);//未变数值
  49. ChangeArrayRef(ref arr2);
  50. Console.WriteLine("调用ChangArrayValueRef函数之后arr2的数值{0}", arr2[0]);//改变数值
  51. Console.WriteLine("********************************");
  52. int[] arr11 = { 100, 200, 300 };
  53. Console.WriteLine("arr11[0]原数值{0}", arr11[0]);//改变数值
  54. ChangeArrayValueRef(ref arr11);
  55. Console.WriteLine("调用ChangArrayValueRef函数之后arr[0]的数值{0}", arr11[0]);//改变数值
  56. Console.WriteLine("********************************");
  57. }
  58. }
  59. }

image

Out

  1. //添加两个OUt修饰参数的函数
  2. static void ChangeValueOut(out int value)
  3. {
  4. value = 3;
  5. }
  6. static void ChangeArrayOut(out int[] arr)
  7. {
  8. arr = new int[] { 666, 777, 888, 999 };
  9. }
  10. //添加到Main函数中
  11. int a1 = 1;
  12. Console.WriteLine("a1原数值{0}", a1);
  13. ChangeValue(a1);
  14. Console.WriteLine("调用ChangValue函数之后a1的数值{0}", a1);//未改变数值
  15. ChangeValueOut(out a1);
  16. Console.WriteLine("a1调用ChangValueOut函数之后a1的数值{0}", a1);//改变数值
  17. Console.WriteLine("********************************");
  18. int[] arr1 = { 100, 200, 300 };
  19. Console.WriteLine("arr1[0]原数值{0}", arr1[0]);
  20. ChangeArray(arr1);
  21. Console.WriteLine("调用ChangArray函数之后arr1[0]的数值{0}", arr1[0]);//未改变数值
  22. ChangeArrayOut(out arr1);
  23. Console.WriteLine("调用ChangArrayOut函数之后arr1[0]的数值{0}", arr1[0]);//改变数值

image

区别:

  1. ref传入的变量必须初始化 out不必
  2. out传入的变量必须在内部进行赋值 ref不必

理解:ref在传入时候已经有初始值,所以在内部可以不作修改,

? out在传入时候可能未有初始值,所以要保证有效,在内部必须进行赋值。

函数的变长参数关键字 ---params

  1. 其后只能跟数组
  2. 数组类型可以为任意类型
  3. 函数参数列表中只能出现一个params,并且修饰的参数只能在末尾出现
  1. //函数变长参数关键字 params后必须为数组
  2. //求n个int的和
  3. int Sum(params int[] arr)
  4. {
  5. int sum=0;
  6. for(int i=0;i<arr.Length;i++)
  7. {
  8. sum+=arr[i];
  9. }
  10. return sum;
  11. }
  12. void Chat(string name,params string[] things)
  13. {
  14. //函数体...
  15. }

函数的参数默认值

函数参数列表中可以有多个参数,有默认值的参数一定在普通参数的后面

  1. void Speak(string thing="我没什么可说的了")
  2. {
  3. Console.WriteLine(thing);
  4. }
  5. //调用
  6. Speak();
  7. Speak("我想说,,,,");

函数重载:

在同一语句块中,函数名字相同,函数的参数列表不同(参数类型不同或参数的个数不同,二者均相同则参数顺序不同)

  1. //函数重载
  2. //函数的参数数量不同
  3. int Sum(int a,int b)
  4. {
  5. return a+b;
  6. }
  7. int Sum(int a,int b,int c)
  8. {
  9. return a+b+c;
  10. }
  11. // 参数 数量相同 类型不同
  12. float Sum(int a,int b)
  13. {
  14. return a+b;
  15. }
  16. float Sum(float f1,float f2)
  17. {
  18. return f1+f2;
  19. }
  20. //参数 数量相同 类型相同 顺序不同
  21. float Sum(float f,int i)
  22. {
  23. return f+i;
  24. }
  25. float Sum(int i,float f)
  26. {
  27. return f+i;
  28. }
  29. //ref 和 out 改变参数类型 与普通的函数构成重载
  30. //ref 和out 算作一类 自身不可互相构成重载
  31. int Sum(int a,int b)
  32. {
  33. return a+b;
  34. }
  35. int Sum(ref int a,int b)
  36. {
  37. return a+b;
  38. }
  39. //params 可以作为重载
  40. //但是 参数默认值不可构成重载

递归函数

函数自己调用自己,递归有递归基与结束调用的条件.

  1. //递归打印0-10
  2. void Fun(int a)
  3. {
  4. if(a>10)
  5. return;
  6. Console.WriteLine(a);
  7. a++;
  8. Fun(a);
  9. }
  10. //递归----求某一数的阶乘
  11. int getFactorial(int a)
  12. {
  13. //结束条件
  14. if(a==1)
  15. return 1;
  16. //递归基
  17. return a*getFactorial(a-1);
  18. }
  19. //递归----求1!+2!+3!+···+10!
  20. int getFactorialSum(int num)
  21. {
  22. if(num==1)
  23. return 1;
  24. return getFactorial(num)+getFactorial(num-1);
  25. }
  26. //递归---
  27. //一根竹竿长100m,每天砍掉一半,求第十天的长度是多少?
  28. void getLong(float length,int day=0)
  29. {
  30. length/=2;
  31. if(day==10)
  32. {
  33. Console.WriteLine("第十天砍后的竹子长度为{0}米"length);
  34. }
  35. ++day;
  36. getLong(length,day);
  37. }
  38. //---递归打印1-200
  39. //递归+短路
  40. bool Fun5(int num)
  41. {
  42. Console.WriteLine(num);
  43. return num==200||Fun5(num+1);//第一个为条件真 便会短路
  44. }

结构体

结构体是数据与方法的集合,在namespace

命名规则:帕斯卡命名法(首字母均大写)

构造函数:

  1. 无返回值
  2. 必须与结构体名字相同
  3. 必须有参数
  4. 如有构造函数,必须把所有的变量进行赋值
  1. //结构体
  2. struct Student
  3. {
  4. //不可以包含自身类型的结构体--Student s; 报错!
  5. //姓名:
  6. public string name;
  7. //年龄
  8. public int age;//数值变量不可以直接初始化
  9. public bool sex;
  10. //构造函数(默认有一个无参构造函数,若有构造函数则默认的构造函数不会失效,这点与类不同)
  11. //对变量进行初始化
  12. public Student(string name,int age,bool sex)
  13. {
  14. this.name=name;
  15. this.age=age;
  16. this.sex=sex;
  17. }
  18. //方法
  19. public void Speak()
  20. {
  21. Console.WriteLine("你好");
  22. }
  23. }
  24. //结构体的使用
  25. Student s1;
  26. s1.name="Tony";
  27. s1.age=18;
  28. s1.sex=true;
  29. s1.Speak();

访问修饰符

  1. public
  2. private(默认不写算私有)
  3. protect 继承的可以访问
  4. internal - 内部的 只有在同一个程序集的文件中,内部类型或者是成员才可以访问

既然都看到这里了,那就给个??吧!
小小一赞,给作者的莫大的鼓励!
关注我,我会每天更新C#学习笔记,从入门到进阶,一起来学习啊!!!

原文链接:https://www.cnblogs.com/TonyCode/p/17757597.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号