C#学习笔记--复杂数据类型、函数和结构体
C#基础
复杂数据类型
特点:多个数据变量地一个集合体,可以自己命名
种类:枚举、数组和结构体
- 枚举:整型常量的集合
- 数组:任意变量类型的顺序存储的数据集合
- 结构体:任意变量类型的数据组合成的数据块
枚举:
枚举可以方便表示对象的各种状态,本质还是一种变量。
例如我们可以用枚举来表示怪物的种类、玩家的动作状态(静止、战斗、受伤......)
枚举的声明:
enum E_MonsterType//命名E_XXX
{
Normal,//0
Boss,//1 自动根据上一个数值顺延
}
enum E_PlayerType
{
Main,
Other,
}
枚举类型的使用:
//自定义的枚举类型 变量名 = 默认值;(自定义的枚举类型.枚举项)
E_PlayerType playerType = E_PlayerType.Other;
if( playerType == E_PlayerType.Main )
{
Console.WriteLine("主玩家逻辑");
}
else if(playerType == E_PlayerType.Other)
{
Console.WriteLine("其它玩家逻辑");
}
//枚举也常常与switch语句做配合
//枚举和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;
playerType=0;
- 枚举与string互转:
playerType=(E_PlayerType)Enum.Paese(typeof(E_PlayerType),"other");
string str=playerType.ToSring();
数组:
数组是存储同一种特定变量类型的有序数据集合,内存上的连续存储。
一维数组
//数组声明
int[] arr1;//未分配内存地址
int[] arr2=new int[5];//元素默认值0
int[] arr3=new int[5]{1,2,3,4,5};
int[] arr4=new int[]{1,2,3};
int[] arr5={1,2,3,4,5,6};
//数组的使用
arr2.Length;//长度
arr2[0];//获取数组中的元素
arr2[2]=99;//修改内容
//数组的遍历
for(int i=0;i<arr2.Length;i++)
{
//遍历
Console.WriteLine(arr2[i]);
}
//数组的自定义扩容
//声明新的大容量数组,把旧有的进行复制转移
int[] array2 = new int[6];
//搬家
for (int i = 0; i < array.Length; i++)
{
array2[i] = array[i];
}
array = array2;
//自定义实现数组的删除元素
int[] array3 = new int[5];
//搬家 转移
for (int i = 0; i < array3.Length; i++)
{
array3[i] = array[i];
}
array = array3;
//查找数组中元素
//只有遍历数组 找到合适的则终止遍历
int a = 3;
for (int i = 0; i < array.Length; i++)
{
if( a == array[i] )
{
Console.WriteLine("和a相等的元素在{0}索引位置", i);
break;
}
}
多维数组(二维数组)
//二维数组
//声明
int[,] arr;
int[,] arr2=new int[3,4];
int[,] arr3=new int[3,4]{{0,1,2,3},//给元素内容 告诉维度 元素个数
{0,1,2,3},
{0,1,2,3}};
int[,] arr4=new int[,]{{0,1,2,3},//给元素内容 告诉维度
{0,1,2,3},
{0,1,2,3}};
int[,] arr5={{0,1,2,3}, //直接给元素内容
{0,1,2,3},
{0,1,2,3}};
//使用
//获取长度
arr3.GetLength(0);//行的长度
arr3.GetLength(1);//列的长度
//获取元素
arr3[1,1];//第一行第一列的元素
//遍历二维数组
for(int i=0;i<arr3.GetLength(0);i++)
{
for(int j=0;j<arr3.GetLength(1);j++)
{
//访问 具体元素
}
}
//增加数组元素
//思想:新建一个大容量的数组,将小的数组元素复制到大的数组中
//最后修改小的数组索引指向大的数组 实现“数组扩容”
//删除数组元素(同增加)
//查找数组中的元素(遍历比对)
交错数组
交错数组区别于多维数组,是数组的数组,一维数组元素也是数组,且长度不必完全相同。
//交错数组
//声明
int [][] arr1;
int [][] arr2=new int[3][];//不可以规定列的长度
int [][] arr3=new int[3][]{
new int[] {1,2,3,4},
new int[] {1,2,3},
new int[] {1}
};//体会数组的数组的含义!
int [][] arr4=new int[][]{
new int[] {1,2,3,4},
new int[] {1,2,3},
new int[] {1}
};
int [][] arr5={//也可以直接赋值
new int[] {1,2,3,4},
new int[] {1,2,3},
new int[] {1}
};
//数组的使用
//长度
arr3.GetLength(0);//行数
arr3[0].Length;//第0行的长度
//获取元素
arr3[0][2];
//遍历
for(int i=0;i<arr3.GetLength(0);i++)
{
for(int j=0;j<arr3[i].Legth;j++)
{
//访问元素
Console.WriteLine(arr3[i][j]);
}
}
值类型和引用类型
值类型的数值存储在栈(系统分配,自动回收GC,小而快)中、引用类型的存储在堆(大而慢,需手动分配与回收)中,栈中只存储其指针;
值类型在赋值时候将数值拷贝,而引用赋值修改引用指向的内存位置。
值类型:(14+2(枚举、结构体))
- 无符号整型:
byte ushort uint ulong - 有符号整型:
sbyte short int long - 浮点数:
float double decimal - 特殊类型:
bool char - 结构体
- 枚举:
enum
引用类型:(5种)
string 、数组、类、接口、委托
函数
函数本质是封装的代码块,提升代码的复用率,抽象出具体的执行过程。
函数只能存在 struct 与class中
//函数出现在stuct与class中
//函数种类
//1 无参数 无返回值
void sayHellow()
{
Console.WriteLine("Hello World");
}
//2 有参数 无返回值
void sayHellow(string name)
{
Console.WriteLine("Hello,"+name);
}
//3 有参数 有返回值
int Add(int a,int b)
{
return a+b;
}
//4 无参数 有返回值
string getMyName()
{
return "TonyChang";
}
ref 和 out
使用其可以解决在函数内部改变函数外部的变量的数值的问题。
(本质是传参数过程中传的是数值或引用是否完全绑定到同一个数值/内存空间中)
//ref的使用
using System;
namespace CSharpLearn1
{
class Program
{
static void ChangeValue(int value)
{
value = 3;
}
static void ChangeArrayValue(int[] arr)
{
arr[0] = 33;
}
static void ChangeArray(int[] arr)
{
arr = new int[] {666,777,888,999 };
}
static void ChangeValueRef(ref int value)
{
value = 3;
}
static void ChangeArrayValueRef(ref int[] arr)
{
arr[0] = 33;
}
static void ChangeArrayRef( ref int[] arr)
{
arr = new int[] { 666, 777, 888, 999 };
}
static void Main(string[] args)
{
int a1 = 1;
Console.WriteLine("a1原数值{0}", a1);
ChangeValue(a1);
Console.WriteLine("调用ChangValue函数之后a1的数值{0}", a1);//未改变数值
ChangeValueRef(ref a1);
Console.WriteLine("a1调用ChangValueRef函数之后a1的数值{0}", a1);//改变数值
Console.WriteLine("********************************");
int[] arr1 = { 100, 200, 300 };
Console.WriteLine("arr1[0]原数值{0}", arr1[0]);
ChangeArrayValue(arr1);
Console.WriteLine("调用ChangArrayValue函数之后arr1[0]的数值{0}", arr1[0]);//改变数值
Console.WriteLine("********************************");
int[] arr2 = { 100, 200, 300 };
Console.WriteLine("arr2[0]原数值{0}", arr2[0]);
ChangeArray(arr2);
Console.WriteLine("调用ChangArrayValue函数之后arr2[0]的数值{0}", arr2[0]);//未变数值
ChangeArrayRef(ref arr2);
Console.WriteLine("调用ChangArrayValueRef函数之后arr2的数值{0}", arr2[0]);//改变数值
Console.WriteLine("********************************");
int[] arr11 = { 100, 200, 300 };
Console.WriteLine("arr11[0]原数值{0}", arr11[0]);//改变数值
ChangeArrayValueRef(ref arr11);
Console.WriteLine("调用ChangArrayValueRef函数之后arr[0]的数值{0}", arr11[0]);//改变数值
Console.WriteLine("********************************");
}
}
}

Out
//添加两个OUt修饰参数的函数
static void ChangeValueOut(out int value)
{
value = 3;
}
static void ChangeArrayOut(out int[] arr)
{
arr = new int[] { 666, 777, 888, 999 };
}
//添加到Main函数中
int a1 = 1;
Console.WriteLine("a1原数值{0}", a1);
ChangeValue(a1);
Console.WriteLine("调用ChangValue函数之后a1的数值{0}", a1);//未改变数值
ChangeValueOut(out a1);
Console.WriteLine("a1调用ChangValueOut函数之后a1的数值{0}", a1);//改变数值
Console.WriteLine("********************************");
int[] arr1 = { 100, 200, 300 };
Console.WriteLine("arr1[0]原数值{0}", arr1[0]);
ChangeArray(arr1);
Console.WriteLine("调用ChangArray函数之后arr1[0]的数值{0}", arr1[0]);//未改变数值
ChangeArrayOut(out arr1);
Console.WriteLine("调用ChangArrayOut函数之后arr1[0]的数值{0}", arr1[0]);//改变数值

区别:
- ref传入的变量必须初始化 out不必
- out传入的变量必须在内部进行赋值 ref不必
理解:ref在传入时候已经有初始值,所以在内部可以不作修改,
out在传入时候可能未有初始值,所以要保证有效,在内部必须进行赋值。
函数的变长参数关键字 ---params
- 其后只能跟数组
- 数组类型可以为任意类型
- 函数参数列表中只能出现一个
params,并且修饰的参数只能在末尾出现
//函数变长参数关键字 params后必须为数组
//求n个int的和
int Sum(params int[] arr)
{
int sum=0;
for(int i=0;i<arr.Length;i++)
{
sum+=arr[i];
}
return sum;
}
void Chat(string name,params string[] things)
{
//函数体...
}
函数的参数默认值
函数参数列表中可以有多个参数,有默认值的参数一定在普通参数的后面
void Speak(string thing="我没什么可说的了")
{
Console.WriteLine(thing);
}
//调用
Speak();
Speak("我想说,,,,");
函数重载:
在同一语句块中,函数名字相同,函数的参数列表不同(参数类型不同或参数的个数不同,二者均相同则参数顺序不同)
//函数重载
//函数的参数数量不同
int Sum(int a,int b)
{
return a+b;
}
int Sum(int a,int b,int c)
{
return a+b+c;
}
// 参数 数量相同 类型不同
float Sum(int a,int b)
{
return a+b;
}
float Sum(float f1,float f2)
{
return f1+f2;
}
//参数 数量相同 类型相同 顺序不同
float Sum(float f,int i)
{
return f+i;
}
float Sum(int i,float f)
{
return f+i;
}
//ref 和 out 改变参数类型 与普通的函数构成重载
//ref 和out 算作一类 自身不可互相构成重载
int Sum(int a,int b)
{
return a+b;
}
int Sum(ref int a,int b)
{
return a+b;
}
//params 可以作为重载
//但是 参数默认值不可构成重载
递归函数
函数自己调用自己,递归有递归基与结束调用的条件.
//递归打印0-10
void Fun(int a)
{
if(a>10)
return;
Console.WriteLine(a);
a++;
Fun(a);
}
//递归----求某一数的阶乘
int getFactorial(int a)
{
//结束条件
if(a==1)
return 1;
//递归基
return a*getFactorial(a-1);
}
//递归----求1!+2!+3!+···+10!
int getFactorialSum(int num)
{
if(num==1)
return 1;
return getFactorial(num)+getFactorial(num-1);
}
//递归---
//一根竹竿长100m,每天砍掉一半,求第十天的长度是多少?
void getLong(float length,int day=0)
{
length/=2;
if(day==10)
{
Console.WriteLine("第十天砍后的竹子长度为{0}米",length);
}
++day;
getLong(length,day);
}
//---递归打印1-200
//递归+短路
bool Fun5(int num)
{
Console.WriteLine(num);
return num==200||Fun5(num+1);//第一个为条件真 便会短路
}
结构体
结构体是数据与方法的集合,在namespace中
命名规则:帕斯卡命名法(首字母均大写)
构造函数:
- 无返回值
- 必须与结构体名字相同
- 必须有参数
- 如有构造函数,必须把所有的变量进行赋值
//结构体
struct Student
{
//不可以包含自身类型的结构体--Student s; 报错!
//姓名:
public string name;
//年龄
public int age;//数值变量不可以直接初始化
public bool sex;
//构造函数(默认有一个无参构造函数,若有构造函数则默认的构造函数失效)
//对变量进行初始化
public Student(string name,int age,bool sex)
{
this.name=name;
this.age=age;
this.sex=sex;
}
//方法
public void Speak()
{
Console.WriteLine("你好");
}
}
//结构体的使用
Student s1;
s1.name="Tony";
s1.age=18;
s1.sex=true;
s1.Speak();
访问修饰符:
- public
- private(默认不写算私有)
- protect 继承的可以访问
- internal - 内部的 只有在同一个程序集的文件中,内部类型或者是成员才可以访问
C#学习笔记--复杂数据类型、函数和结构体的更多相关文章
- C#学习笔记(七):结构体、数组、冒泡排序和调试
结构体 结构体不能重写默认无参构造函数 一位数组 using System; using System.Collections.Generic; using System.Linq; using Sy ...
- 《objective-c基础教程》学习笔记(三)—— 从结构体到面向对象
一听标题,感觉十分的抽象.面向对象就是(Object-Oriented Programming)的首字母缩写:OOP,是当今最主流的编程方法. 那么,面向对象编程具体有什么好处呢.是如何来实现呢?通过 ...
- iOS学习笔记44-Swift(四)枚举和结构体
一.Swift的枚举 枚举是一系相关联的值定义的一个公共的组类型,同时能够让你在编程的时候在类型安全的情况下去使用这些值.Swift中的枚举比OC中的枚举强大得多, 因为Swift中的枚举是一等类型, ...
- IOS学习笔记06---C语言函数
IOS学习笔记06---C语言函数 -------------------------------------------- qq交流群:创梦技术交流群:251572072 ...
- Typescript 学习笔记三:函数
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- OpenCV 学习笔记03 findContours函数
opencv-python 4.0.1 1 函数释义 词义:发现轮廓! 从二进制图像中查找轮廓(Finds contours in a binary image):轮廓是形状分析和物体检测和识别的 ...
- Go语言学习笔记七: 函数
Go语言学习笔记七: 函数 Go语言有函数还有方法,神奇不.这有点像python了. 函数定义 func function_name( [parameter list] ) [return_types ...
- JavaScript:学习笔记(5)——箭头函数=>以及实践
JavaScript:学习笔记(5)——箭头函数=>以及实践 ES6标准新增了一种新的函数:Arrow Function(箭头函数).本文参考的链接如下: MDN箭头函数:https://dev ...
- Python学习笔记之常用函数及说明
Python学习笔记之常用函数及说明 俗话说"好记性不如烂笔头",老祖宗们几千年总结出来的东西还是有些道理的,所以,常用的东西也要记下来,不记不知道,一记吓一跳,乖乖,函数咋这么多 ...
- IOS学习笔记07---C语言函数-printf函数
IOS学习笔记07---C语言函数-printf函数 0 7.C语言5-printf函数 ------------------------- ----------------------------- ...
随机推荐
- 蔬菜识别系统Python+TensorFlow+Django+卷积神经网络算法
一.介绍 蔬菜识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法.并通过对数据集进行训练,最后得到一个识别精度较高的模型.并基于Django框架,开 ...
- 1. 认识IntelliJ IDEA
恐惧是本能,行动是信仰(在此感谢尚硅谷宋红康老师的教程) 1. Why IDEA ? [注]JetBrains 官方说明: 尽管我们采取了多种措施确保受访者的代表性,但结果可能会略微偏向 JetBra ...
- Linux系统运维之FastDFS集群部署
一.简介 FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储.文件同步.文件访问(文件上传.文件下载)等,解决了大容量存储和负载均衡的问题.FastDFS服务端有两个 ...
- ThinkPHP6.0 链式SQL语句
ThinkPHP6.0 链式SQL语句 查询单个数据 $user = Db::query('select * from `user`'); $user=Db::table('user')->wh ...
- Linux 一些常用命令
Linux命令的分类 1.帮助命令(help) 2.常用系统工作命令 3.常用状态检测命令 4.工作目录切换命令 linux命令在线中文手册 Linux常用命令 echo命令 作用:在终端输出字符串或 ...
- Centos7中Jar快速启动脚本
Centos7中Jar快速启动脚本 创建一个文本,将以下脚本内容复制到文本当中,重命名文本后缀为.sh 注意:根据自己的项目进行更改相关内容,对应注释已说明 #!/bin/sh APP_NAME=ma ...
- 文心一言 VS 讯飞星火 VS chatgpt (67)-- 算法导论6.5 6题
文心一言 VS 讯飞星火 VS chatgpt (67)-- 算法导论6.5 6题 六.在 HEAP-INCREASE-KEY 的第 5 行的交换操作中,一般需要通过三次赋值来完成.想一想如何利用IN ...
- Linux系统安装CH341驱动
Linux系统安装CH341驱动 Linux系统(这里以ubuntu20.04为例)本身会自动安装CH340驱动,随着时间的推移,旧版本的驱动已经无法支持当下的CH340模块,所以我们需要重新安装驱动 ...
- linux vim 无权限保存解决办法
通常在vim编辑文件时往往会忘记文件权限问题, 在wq保存时发现权限不足,这时候输入以下命令解决: w! sudo tee % 命令解析: w! {cmd} 指示 保存时执行额外命令: tee 用于将 ...
- python-gitlab 一个简单demo
背景 需要收集git仓库信息到数据库供前端展示 包括:仓库信息.仓库所有者.成员列表.提交信息.活跃情况等 需要定时启动.灵活触发 实现简介 使用gitlab v4 restful 接口 使用pyth ...