C#???
- ?请纠正文章中的错误。如果你认为它对你有用,请表扬和关注它。谢谢你的支持
- C#
-
- 简介
- C#关键字
- ??C#初次体验
-
- ?使用Visual Studio创建第一个项目 打印`Hello world!`
- ??MSDN
-
- ?MSDN地址
- ??数据类型
-
- ?数据的量级
- ?数据类型
- ?常量、变量
- ??运算符
-
- ?数据的量级
- ?算术运算符
- ?符合运算符
- ?输入与输出
- ??预编译执行 region
- ?类型转换
- ?关系运算符 & 逻辑运算符
- 练习???
- ??分支语句
-
- ?条件运算符
- ?循环语句
- 练习???
- ??数组
-
- ???一维数组的初始化
-
- ??数组的访问
- ??引用数据类型
- ??遍历数组
- ???二维数组、结构体、枚举
-
- ???冒泡排序
- ???定义二维数组
- ???枚举类型
- ???结构体类型
- ???结构练习
- ???面向对象
-
- ??面向过程
- ??面向对象
- ??类和对象
- ???属性、方法参数
-
- ??属性
- ??引用参数ref
- ??输出参数out
- ?? 字符串
- ???StringBuilder、重载、递归
-
- ??StringBuilder
- ???方法的重载
- ??递归
- ???构造函数
- ???多态
-
- ?父空参数构造函数的调用说明
- ?覆盖子类方法
- ?子类方法的重写多态
- ??所有类别的最终基类:**Object**
- ??抽象方法
- ??sealed关键词
- ??静态类
- 集合、栈、堆、队列、字典 ???
-
- 1、集合~范型(命名空间using System.Collections.Generic;)
-
- 1.1、ArrayList
- 1.2、List
- 2、栈(Stack )
- 3、堆(heaps)
- 4、队列(Queue)
- 5、字典(Dictionary
?请纠正文章中的错误。如果你认为它对你有用,请表扬和关注它。谢谢你的支持
提示:以下是本篇文章正文内容
C#
简介
- C##是微软公司发布的一种C和C 面向对象衍生的编程语言不仅去除了 C 和 Java 语言中的一些复杂特征也提供了可视化工具,可以有效地编写程序。
- C#是由C和C 衍生的一种安全、稳定、简单、优雅对象编程语言。它继承了C和C 它们的一些复杂特征(如没有宏,不允许多重继承),不允许多重继承)。
- C#使得C 由于可调用,程序员可以有效地开发程序 C/C 本机原生函数编写,永不损失C/C 强大的原始功能。种继承关系,C#与C/C 熟悉类似语言的开发者可以快速转向C#。
C#关键字
abstract | decimal | finally | in | partial | short/td> | typeof | volatile |
可以和类、方法、属性、索引器及事件一起使用,标识一个可以扩展但不能被实体化的、必须被实现的类或方法。 | ~ | 定义一个代码块,在程序控制离开try代码块后执行。参见try和catch。 | ~ | ~ | ~ | 一个操作符,返回传入参数的类型。 | 标识一个可被操作系统、某些硬件设备或并发线程修改的attribute。 |
as | default | fixed | int | out | set | uint | where |
一个转换操作符,如果转换失败,就返回null。 | ~ | 在一个代码块执行时,在固定内存位置为一个变量指派一个指针。 | ~ | 标识一个参数值会受影响的参数,但在传入方法时,该参数无需先初始化。 | ~ | ~ | ~ |
base | delegate | float | interface | namespace | stackalloc | unchecked | while |
用于访问被派生类或构造中的同名成员隐藏的基类成员。 | 指定一个声明为一种委托类型。委托把方法封装为可调用实体,能在委托实体中调用。 | ~ | 将一个声明指定为接口类型,即实现类或构造必须遵循的合同。 | 定义一个逻辑组的类型和命名空间。 | 返回在堆上分配的一个内存块的指针。 | 禁止溢出检查。 | ~ |
bool | continue | for | internal | override | sizeof | ulong | yield |
true/false | ~ | ~ | 一个访问修饰符。 | ~ | 一个操作符,以byte为单位返回一个值类型的长度。 | ~ | ~ |
break | double | foreach | is | private | static | unsafe | class |
终止循环语句 | ~ | 用于遍历一个群集的元素。 | ~ | ~ | ~ | 标注包含指针操作的代码块、方法或类。 | ~ |
byte | do | get | lock | ref | this | void | true |
范围是0~255 | ~ | ~ | ~ | 标识一个参数值可能会受影响的参数。 | ~ | ~ | ~ |
case | else | goto | long | readonly | struct | ushort | extern |
~ | ~ | 一个跳转语句,将程序执行重定向到一个标签语句。 | ~ | 标识一个变量的值在初始化后不可修改。 | 是一种值类型,可以声明常量、字段、方法、property、索引器、操作符、构造器和内嵌类型。 | ~ | 标识一个将在外部(通常不是c#语言)实现的方法。 |
catch | enum | if | new | public | throw | using | false |
定义一个代码块,在特定类型异常抛出时,执行块内代码。 | 表示一个已命名常量群集的值类型。 | ~ | ~ | ~ | 抛出一个异常。 | 当用于命名空间时,using关键字允许访问该命名空间中的类型,而无需指定其全名。也用于定义finalization操作的范围。 | ~ |
char | event | implicit | null | return | try | value | sbyte |
~ | 允许一个类或对象提供通知的成员,他必须是委托类型。 | 一个操作符,定义一个用户定义的转换操作符,通常用来将预定义类型转换为用户定义类型或反向操作,隐式转换操作符必须在转换时使用。 | ~ | ~ | 异常处理代码块的组成部分之一。try代码块包括可能会,抛出异常的代码。参阅catch和finally关键字。 | ~ | ~ |
checked | explicit | const | object | protected | switch | virtual | sealed [18] |
既是操作符又是语句,确保编译器运行时,检查整数类型操作或转换时出现的溢出。 | 一个定义用户自定义转换操作符的操作符,通常用来将内建类型转换为用户定义类型或反向操作,必须再转换时调用显示转换操作符。 | 标识一个可在编译时计算出来的变量值,即一经指派不可修改的值。 | ~ | ~ | ~ | 一个方法修饰符,标识可被覆载的方法。 | 防止类型被派生,防止方法和property被覆载。 |
🍺C#初次体验
⌨使用Visual Studio创建第一个项目 打印Hello world!
创建项目
打开VS->新键项目->找到控制台程序(.NET Framework)->下一步->创建 eg:
打印Hello world!
🔔如何编译当前程序?
1.C#程序–人能看懂,机器看不懂 2.执行程序的确是机器 3.需要将C#程序编译(翻译)成机器能够读懂的语言(二进制) 4.这样程序就可以被机器执行了 5.Windows:生成->生成解决方案 Ctrl + Shift + B
🔔如何运行当前程序? 1.Windows:运行而不调试(Ctrl + F5/F5) eg:
🔔注释 1.注释是不会被编译的,更不会被执行 2.注释的作用: 3.解释说明当前的代码是什么含义 3.1、强调 1.在目前学习代码阶段,保证你写的每行代码都要配一行注释 2.解释说明,你这句代码是什么含义 3.1、暂时取消某些代码的执行 快捷键: 注释当前选中行的代码:Ctrl + K + C 取消注释当前选中行的代码:Ctrl + K + U
🍺MSDN
⌨MSDN地址
https://docs.microsoft.com/zh-cn/dotnet/api/system.reflection.fieldinfo?view=netframework-4.7.2
🍺数据类型
⌨数据的量级
- 1024字节(byte)=1KB
- 1024KB = 1MB
- 1024MB = 1GB
- 1024GB = 1TB
- 1024TB = 1PB
⌨数据类型
- bool 0000 0000 0000 0001
- sbyte 有符号的8位整数 000 0000 — 111 1111 (0-127) 1.第一位表示符号(+ -) 2.特殊0:1000 0000 和 0000 0000 3.硬性规定:1000 0000 表示-128 4.取值范围:-128—+127
- byte无符号的8位整数 1.0000 0000 —— 1111 1111 2.取值范围 0 ——255
- short有符号的16位整数(文档中是Int16) 1.000 0000 0000 0000 —— 111 1111 1111 1111 2.负32768到正32767
- int有符号的32位整数(文档中是Int32)
- 一般说整型即int类型
- 无特殊情况,存储一个整数都用int
- (面试经常问)
- long有符号的64位整数(文档中是Int64)
- 浮点数(通常理解就是生活中的小数)
- float(单精度浮点数)【文档中查:Single】
- 一般情况下,float足够
- double(双精度浮点数)【文档中查:Double】
- 如果需要精度更高一点,用Double
- decimal(高精度浮点数)
- 极少用到,天文数字可能会用到这个
- float(单精度浮点数)【文档中查:Single】
⌨常量、变量
- 程序运行期间
- 程序开始到程序结束
- 变量:在程序运行期间,可以被改变
- 变量的声明
- 数据类型 变量名 = 初值;
- ⌨ int a = 10;
- 变量可以不赋初值(在特殊情况下必须要赋初值)
- 不赋初值时,当前变量的值是默认值
- int/float 默认值是0
- char 默认值’\0’(表示空字符)
- 不赋初值时,当前变量的值是默认值
- 变量的声明
- 常量:在程序运行期间,不能被改变
- 常量的声明
- const 数据类型 变量名 = 初值;
- 大写(潜规则)
- ⌨ const float money = 100.35f;
- 常数必须要赋初值
- 常量的声明
- 浮点型声明时注意:
- float flo = 1.11f;【float数字后面要加f】
- double damage = 1.11d【double后面要加d】
- decimal damage = 1.223m【decimal后面要加m】
- 字符型声明注意:
- 字符类型(一定要用单引号括起来)
- char cha = ‘name’;
- 常量及变量的命名规则
- 只能由字母、数字、@和下划线(_)这些组成
- 数字不能开头,⌨ 1a❌、3f❌、xiaoming1✅
- @符号,要么不用,要用必须放在首位,🌰@zhansan✅,zhang@san❌
- 不能与系统的关键词同名,⌨ int,long,sbyte❌
- 变量名不能重复
- 中文变量名语法上是可以的,但极为不推荐
- 常量及变量的命名
- 全是英文单词,不要用拼音
- 驼峰命名法
- 大驼峰(每个单词的首字母大写,其余字母小写)
- MyHeroDamage、HeroAttack
- 小驼峰:(第一个单词首字母不大写,后面每个单词的首字母大写,其余字母小写)
- myHeroDamage、heroAttack【目前阶段都用小驼峰】
- 大驼峰(每个单词的首字母大写,其余字母小写)
- 见名知意
- yyds(你晓得这是啥?评论区见)❌
🍺运算符
⌨数据的量级
- 赋值运算符 “=”,是一个,将后面的结果赋给前面的变量或常量
- 前面 = 后面;后面的值赋给前面
- 前面必须是个变量【不能是具体是数值(2,3,’A‘,“123”)】
- 后面可以是具体的数值,也可以是变量,也可以是常量
⌨算术运算符
- +、- 加减法
- *、/ 乘除法
- a / b 运算之后得到一个结果
- 被除数 ÷ 除数 = 商
- 除法有一个禁忌:除数不能为0
- % 取余(做除法取余数)
- 5 % 3 : 5除以3,得到的余数,是结果
- 上面的+、-、*、/、%都是二元运算符
- ++运算符和–运算符
- 举例:a++; 等价于 a = a+1;
- ++、- -是一元运算符
//int showYouAge = age++;//结果是18
//意味着 age++ 得到的结果是 age
//解析:
//第一步:将age的值赋给showYouAge
//第二步:age自增
int showYouAge = ++age;
//意味着 ++age 得到的结果是 age+1
//解析:
//第一步:age自增
//第二步:将age的值赋给showYouAge
//总结:
//age++;++age;
//++符号在前就先自增,后赋值
//++符号在后就先赋值,后自增
练习题:
⌨符合运算符
- a+=b;等价于a=a+b;
- ==>
- a-=b;等价于a=a-b;
- a*=b;等价于a=a*b;
- a/=b;等价于a=a/b;
- a%=b;等价于a=a%b;
⌨输入与输出
- 输出
- Console.WriteLine();
- 输出内容,并换行
- Console.Write();
- 输出内容,不换行
- Console.WriteLine();
- 输入
- Console.Read();
- 从屏幕读取一个字符,并返回该字符所对应的整型数字
- Console.ReadLine();
- 从屏幕读取一串字符,并返回该字符串
- 字符串是一个数据类型
- 关键词string
- 表示一串字符
- 用双引号括起来
- 字符串相加可以得到两个字符串组合到一起的字符串
- Console.Read();
📚预编译执行 region
- 作用:代码分成一个区域,方便折叠和展开
- 区域首部:#region
- 区域尾部:#endregion eg:
⌨类型转换
- 隐式转换
- 将占用字节小的、取值范围小的、精度小的,转换为占用字节大的、取值范围大的、精度高
- 不需要任何的修饰符,会自动转换
//整型
//1 2 4 8
//sbyte short int long
sbyte englishScore = 100;
//sbyte --> int
int myScore = englishScore;
//int --> long
long classScore = myScore;
//int --> float
float newScore = myScore;
//float --> double
double newClassScore = newScore;
- 显式转换(强制转换)
- 将占用字节大的、取值范围大的、精度高,转换为占用字节小的、取值范围小的、精度小的
- 需要强制转修饰符,
- 转换情况:知道这个数字,在小的数据类型的取值范围内
//强制转换
int damage = 10000;
//int --> sbyte
sbyte health = (sbyte)damage;
//输出结果
Console.WriteLine(health); //16
float mathScore = 90.5f;
//float --> int
int myAllScore = (int)mathScore;
//会把小数点后面的内容全部舍去
Console.WriteLine(myAllScore); //90
- int和char之间的类型转换
//int 和 char之间的类型转换
int num = 11101;
//int --> char
char letter = (char)num;
//a-97
Console.WriteLine(letter);
评论区请教大神!!!
- int和bool之间的类型转换
- 不能进行转换
- string与其他类型之间的转换
- 举例:
- “false”,“true”
- “10”,“3.14”
- “A”
- 转换方法
- System.Convert
- System.Convert.ToBoolean()
- System.Convert.ToInt32()
- System.Convert.ToSingle()
- System.Convert.ToDouble()
- System.Convert.ToChar()
- 数据类型.Parse()
- int.Parse()
- bool.Parse()
- float.Parse()
- char.Parse()
- System.Convert
- 其他类型能不能转换成字符串
- 其他类型的变量.ToString();
- 举例:
⌨关系运算符 & 逻辑运算符
- 关系运算符:>,<,>=,<=,==,!=
- 逻辑运算符:逻辑运算是bool与bool之间的运算
- &:与运算
- true & true : true
- true & false : false
- false & false : false
- 总结:一假则假
- |:或运算
- true | true : true
- true | false : true
- false | false : false
- 总结:一真则真
- !:非运算
- ! true : false
- ! false : true
- &&:短路与运算
- 普通的&与运算,无论第一个条件是真是假,都会继续判断第二条件
- 短路与运算&&,如果判断第一个条件已经是假,则不会继续判断第二个条件
- ||:短路或运算
- 普通的|与运算,无论第一个条件是真是假,都会继续判断第二条件
- 短路或运算||,如果判断第一个条件已经是真,则不会继续判断第二个条件
- 短路&&、||
- 优点:第一个条件已经得知整个逻辑运算的结果,就不会去判断第二个条件了
- 节约了运算量
- 缺点:如果判断中带有运算,如果不进行第二个条件的判断,那第二个条件中的运算也不能执行
- 优点:第一个条件已经得知整个逻辑运算的结果,就不会去判断第二个条件了
- &:与运算
练习:👍👍👍👍👍👍
- 手动计算下列表达式的值和number的值,并编写程序来验证结果是否正确
- ①number初值为6:number++ * ++number - number-- / --number
- ②number初值为5:number++ > 3 | --number == 0
- ③number初值为2:number-- > 2 && --number == 0
- ④number初值为12:number++ > 10 && --number != 2 && number-- == 0 && ++number != 3
- ⑤number初值为0:number++ > -1 || --number <= 2 && number-- != 10
- ⑥number初值为0:number++ < -1 || (–number >= 2 && number-- != 10)【小括号优先级最高】
🍺分支语句
⌨条件运算符
- 条件运算符(三元运算符)
- 条件表达式 结果a 结果b
- if的第一种形式
if(条件表达式){
语句1;
}
- if的第二种形式
if (条件表达式)
{
语句1;
}
else
{
语句2;
}
- if的第三种形式
if (条件表达式1)
{
语句1;
}
else if (条件表达式2)
{
语句2;
}
else
{
语句3;
}
- Switch
- 如果case 冒号后面没有任何语句,可以不加break;
- Switch()括号中是可以允许添加浮点型变量的,但
- 浮点型是有误差的
- 浮点型一般不做等于的判断
- 企业面试题:有一个浮点数,判断该浮点数是不是等于5
⌨循环语句
- while循环
while (条件表达式)
{
//循环内容
}
- break关键词
- 跳出本循环(通常与if连用)
- continue关键词
- 结束循环(continue后面的代码不再执行),进入下次循环。(通常与if连用)
练习:👍👍👍👍👍👍
- 从键盘输入一个算数运算式,使用if语句实现正确的算数运算,并输出运算结果
- 例如:
- 请输入第一个数字:4
- 请输入运算符:+
- 请输入第一个数字:2
- 例如:
- 输入一个生日日期,输出其星座. 白羊座:3.21-4.19,金牛座:4.20-5.20,双子座:5.21-6.21,巨蟹座:6.22-7.22 狮子座:7.23-8.22,处女座:8.23-9.22,天秤座:9.23-10.23,天蝎座:10.24-11.22 射手座:11.23-12.21,魔羯座:12.22-1.19,水瓶座:1.20-2.18,双鱼座:2.19-3.20
- 例如:
- 请输入月:12
- 请输入日:21
- 例如:
🐖数组
🉑🉑一维数组的初始化
- 动态初始化
- 数据类型[] 数组名=new 数据类型[数组长度];
- 此时数组中每一个元素都是为默认值
- int的默认值0
- float的默认值0
- bool的默认值false
- char的默认值‘\0’,表示空字符
- string的默认值""
- 此时数组中每一个元素都是为默认值
- 数据类型[] 数组名=new 数据类型[数组长度]{元素1,元素2…};
- 数据类型[] 数组名=new 数据类型[]{元素1,元素2…};
- 数据类型[] 数组名=new 数据类型[数组长度];
- 静态初始化
- 数据类型[] 数组名={元素1,元素2…};
🉑数组的访问
- 从开始计数
- array.Length是数组的长度,只读的。
- 访问数组时,切记下标所对应的数组元素是存在的
- 如果不存在,就会引发
🉑引用数据类型
- 数据类型
- 值类型(存储在栈内存)
- 栈内存里存的是具体的值
- 前面学习过的值类型
- int、float、bool、char
- 引用类型(存储在堆内存)
- 栈内存里存的是地址(堆内存的地址)
- 目前学习过的引用类型
- string(特例)、数组
- 值类型(存储在栈内存)
🉑遍历数组
- 遍历数组:访问数组中的每一个元素
int[] array = { 1,8,4,8,7,45,456,789,78,76};
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine(i + ":" + array[i]);
}
👂👂二维数组、结构体、枚举
👂👂冒泡排序
- 思想:
- 当前数组元素与后面的数字元素进行对比,如果前大后小,则进行交换
- 每轮可以确定一个最大值在数组的末位,几轮之后即可完成排序
- 冒泡排序当然也可以从大到小排序,那样则前小后大进行交互 代码:
for (int i = 0; i < array.Length; i++)
{
//立个flag,表示判断过程中是否发生了交换
bool IsjiaoHuan= false;
for (int j = 0; j < array.Length - i - 1; j++)
{
if (array[j] > array[j + 1])
{
//说明交换了
IsjiaoHuan= true;
//交换
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
if(!IsjiaoHuan)
{
//说明已经排好序了,后面的轮次就没有必要了
break;
}
for (int m = 0; m < array.Length; m++)
{
Console.Write(array[m] + "\t");
}
Console.WriteLine();
}
Console.WriteLine("排序结束");
for (int m = 0; m < array.Length; m++)
{
Console.Write(array[m] + "\t");
}
👂👂二维数组的定义
- 数据类型[,] 数组名;
👂int[,] array;
- 二维数组的初始化
- 动态初始化
- 数据类型[,] 数组名 = new 数据类型[第一维长度,第二维长度];
👂int[,] arr= new int[50,3];
- 数据类型[,] 数组名 = new 数据类型[,]{数组值};
👂int[,] arr= new int[,]{ {1,0,1},{3,0,5}};
- 数据类型[,] 数组名 = new 数据类型[第一维长度,第二维长度];
- 静态初始化
- 数据类型[,] 数组名 = {数组值};
👂int[,] arr= { {1,0,1},{3,0,5}};
- 数据类型[,] 数组名 = {数组值};
- 动态初始化
- 二维数组的元素访问
- 数组名[第一维下标,第二维下标]
👂 arr[3,2]
- 谨防数组越界
- 数组名[第一维下标,第二维下标]
- 二维数组的长度
- 总长度(二维数组的元素个数)
- array.Length
- 第一维的长度
- array.GetLength(0)
- 第二维的长度
- array.GetLength(1)
- 总长度(二维数组的元素个数)
- 二维数组的遍历
for (int i = 0; i < heroData.GetLength(0); i++)
{
for (int j = 0; j < heroData.GetLength(1); j++)
{
Console.Write(heroData[i,j] + "\t");
}
//换行
Console.WriteLine();
}
- foreach迭代遍历
- 迭代遍历是只读的,不能修改
//foreach性能消耗要大一点,所以能用for的尽量用for
foreach (var item in number)
{
Console.WriteLine(item);
//迭代遍历是只读的,不能写入
//item = 1;
}
👂👂枚举类型
- 枚举类型是一个自定义类型
- 枚举类型是一个值类型
- 枚举类型的创建
//装备类型
enum EquipType
{
Helmet = 100,//头盔
BodyArmor = 200,//防弹衣
Knapsack,//背包
Knife
}
- 枚举类型变量的定义与使用
//定义一个枚举类型的变量
EquipType myEquip = EquipType.Knapsack;
EquipType yourEquip = EquipType.Knapsack;
//判断枚举变量
if(myEquip == EquipType.BodyArmor) { }
switch (myEquip)
{
case EquipType.BodyArmor:
break;
case EquipType.Helmet:
break;
case EquipType.Knife:
break;
//case EquipType.
default:
break;
}
//枚举类型和整型之间的转换
//枚举类型可以强制转换为整型
int num = (int)myEquip;
Console.WriteLine(num);
//整型可以强制转换为枚举类型
myEquip = (EquipType)200;
Console.WriteLine(myEquip);
//既然枚举可以用整数去表示
Console.WriteLine(myEquip+2);
👂👂结构体类型
- 结构体类型是自定义类型
- 结构体类型是值类型
- 结构体类型的创建
//学生类型
struct Student
{
public string name;
public char sex;
public int age;
}
- 结构体类型变量声明及字段赋值
//定义一个学生变量
Student xiaoming;
//学生结构内变量赋值
xiaoming.name = "xiaoming";
xiaoming.age = 16;
xiaoming.sex = 'M';
- 结构体的构造函数
- 结构体默认的构造函数,开发者不能创建默认构造(即无参构造)
public Student()
{
}
- 结构体的自定义构造函数,方便创建结构体变量时给字段赋值
//自定义构造函数
public Student(string n,char s,int a)
{
//作用:快速给结构体字段赋初值
//而且必须给每一个字段都赋初值
name = n;
sex = s;
age = a;
}
- 初始化结构体变量
//有了自定义的构造函数后,如何新建结构体变量
Student xiaogang = new Student("xiaogang",'M',18);
👂👂结构体练习题
eg:
#region 结构体、枚举
//创建英雄装备结构体,包含名称,攻击力加成,法术强度加成,血量加成,装备类型
enum EquipType
{
AD,
AP,
HP,
Other
}
//英雄装备
struct HeroEquip
{
public string name;
public float adAddition;
public float apAddition;
public float hpAddition;
public EquipType equipType;
public HeroEquip(string name, float adBuff, float apBuff, float hpBuff, EquipType equipType)
{
//给所有字段赋初值
this.name = name;
adAddition = adBuff;
apAddition = apBuff;
hpAddition = hpBuff;
this.equipType = equipType;
}
}
#endregion
#region 结构体、枚举练习
//有5个装备保存在结构体数组当中,编程找出血量加成最高者
//对装备数组按照攻击力加成排序并使装备按照攻击力加成升序进行信息打印
HeroEquip wjzr = new HeroEquip(
"无尽之刃", 100, 0, 50, EquipType.AD);
HeroEquip yxj = new HeroEquip(
"饮血剑", 80, 0, 20, EquipType.AD);
HeroEquip ktkj = new HeroEquip(
"狂徒铠甲", 0, 0, 150, EquipType.AD);
HeroEquip dmj = new HeroEquip(
"兰德里的折磨", 20, 100, 0, EquipType.AD);
//声明结构体数组存储这些装备
HeroEquip[] heroEquips = { wjzr, yxj, ktkj, dmj };
//设置初始血量最大值
float maxHPBuff = heroEquips[0].hpAddition;
//设置初始血量最大值的装备名称
string maxHPEquipName = heroEquips[0].name;
HeroEquip maxHPEquip = heroEquips[0];
//找血量最大
for (int i = 0; i<heroEquips.Length; i++)
{
if (maxHPBuff<heroEquips[i].hpAddition)
{
//更新最大值
maxHPBuff = heroEquips[i].hpAddition;
//更新最大值的装备名称
maxHPEquipName = heroEquips[i].name;
}
//如果声明结构体
if (maxHPEquip.hpAddition<heroEquips[i].hpAddition)
{
maxHPEquip = heroEquips[i];
}
}
Console.WriteLine("装备列表中,血量加成最高的装备是\n"
+ maxHPEquip.name + ",最大值是"
+ maxHPEquip.hpAddition);
Console.Read();
#endregion
🍺🍺🍺面向对象
⌨⌨面向过程
- 重点关心
- 优点:
- 可以很清晰的看明白问题解决的步骤
- 代码的行数要少一些,性能消耗低一些
- 缺点:
- 不易维护、不易拓展、不易复用
⌨⌨面向对象
- 重点关心解决问题过程中参与的有哪些,分别有哪些特性和行为
- 优点:
- 易维护、易拓展、易复用
- 缺点:
- 代码是分散的,行数会多一些
- 性能消耗要高一些
⌨⌨类和对象
- 创建一个类
[访问修饰符] Class 类名//大驼峰命名法
- 创建一个类的对象
类名 对象名;
- 类的类型是一个
- 类的类型是一个自定义类型
- 一个对象在创建后,需要进行实例化(初始化)才能使用
类名 对象名 = new 类名();
- 原理 : 对象在进行new操作后,才分配了内存。
- 字段
- 描述类的特性
- 要使用小驼峰命名法命名
- 可以有初值
- 帮助注释
- 帮助注释也是一种注释
- 谁可以添加帮助注释
- 类
- 方法
- 字段
- 属性
- 帮助注释的优点
- 在使用类、方法、字段、属性的时候,可以在提示框中显示帮助注释的内容
- 字段
- this关键词
- 表示当前对象
- 如果没有重名冲突,可以不写(省去)
- Random随机数类
- 第一步,先创建一个随机数对象
Random random = new Random();
-
第二步,调用随机数对象的Next方法
- 调用时要传入两个参数,即随机数字的取值范围 - 如传入的是4和8,则随机数字范围为4至7,不包含8(这个方法就是这么写的) - 即取值范围为左闭右开,即[min,max) - 方法返回的结果即随机到的数字,需要用整型变量去接收
int num = random.Next(0,array.Length);
- 方法
- 方法是描述一个类的某个特定行为
- 一个方法尽量就完成一件小的事情
- 如果要完成一件大事
- 先定义一些方法,完成这个大事拆分出来的小事
- 最后在按照流程,在大事方法中调用这些小事的方法
- 如果要完成一件大事
- 方法要用大驼峰命名法命名
- 方法的创建
[访问修饰符] 返回值类型 方法名(参数列表)
{
//方法体
//实现方法功能
return 结果;//最终别忘了返回方法结果,结果类型需与返回值类型保持一致
}
- 方法的调用
对象名.方法名(参数列表);//无论有无参数,小括号都要存在
- return关键词
- 返回结果
- 终止方法,即return后面的语句不会执行
🍺🍺属性、方法参数
⌨⌨属性
- 属性命名方式使用
- 在属性访问器内写代码,切记一点
- Get访问器内不要写读取该属性的语句
- Set访问器内不要写写入该属性的语句
- 否则,会出现递归循环,死循环
- 属性简写:public string Name { get; set; } = “先生”;
⌨⌨引用参数ref
- 添加了ref关键词的参数
- 传递的就不是值了
- 而是地址
- 而如果没有赋初值,是没有地址的
- 所以ref参数
- 所以ref参数的
- 所以ref一般加在值类型参数的前面
- 使用应用参数,无论是形参还是实参前面都要加ref关键词
⌨⌨输出参数out
- 添加了out关键词的参数
- 参数就成了一个输出的通道
- 离开方法之前形参必须赋值
- 实参
- 传递的实参一般是
- 使用输出参数,无论是形参还是实参前面都要加out关键词
🍺 字符串
Contains | Contains |
---|---|
Remove | LastIndexOf |
public string Remove(( int startIndex)/ (int startIndex, int count )) | public int LastIndexOf( (string/char) value ) |
CopyTo | PadLeft |
从 string 对象的指定位置开始复制指定数量的字符到 Unicode 字符数组中的指定位置。 | 补充左边长度:.PadLeft(2, ‘0’) |
Format | PadRight |
把指定字符串中一个或多个格式项替换为指定对象的字符串表示形式。 | 补充右边长度:.PadRight(2, ‘0’) |
IndexOf | Replace |
返回指定 Unicode 字符在当前字符串中第一次出现的索引,索引从 0 开始。 | 替换文字:stringObj.replace(“终古”,“中国”); |
Insert | Split |
返回一个新的字符串,其中,指定的字符串被插入在当前 string 对象的指定索引位置。 | 返回一个字符串数组,包含当前的 string 对象中的子字符串,子字符串是使用指定的 Unicode 字符数组中的元素进行分隔的。 |
Join | ToLower |
连接一个字符串数组中的所有元素,使用指定的分隔符分隔每个元素。 | 把字符串转换为小写并返回。 |
Substring | ToUpper |
string substr = str.Substring(23); | 把字符串转换为大写并返回。 |
Trim | |
移除当前 String 对象中的所有前导空白字符和后置空白字符。 |
🍺🍺StringBuilder、重载、递归
⌨⌨StringBuilder
- 在System.Text命名空间下
- 所以使用时,需要先引入这个命名空间
using System.Text;
- 如果不引入,可以直接写:
System.Text.StringBuilder strB = new System.Text.StringBuilder();
- 使用时,先要new
StringBuilder stringB = new StringBuilder();
- 追加字符串
//追加字符串
stringBuilder.Append("天气好晴朗");
- 什么时候用StringBuilder而不用string
- 字符串需要经常修改的时候
⌨⌨⌨方法的重载
- 同一个类里面,方法名一样,但参数不一样
- 参数的数据类型不一样
- 参数的个数不一样
- 参数的数据类型不一样,个数也不一样
- 参数个数和类型都一样,但返回值类型不一样,不能算做重载❌
class Funs
{
public string Fun(string a, string b)
{
return "a+b";
}
public int Fun(int a, int b)
{
return a + b;
}
}
Funs funs = new Funs();
int a = funs.Fun(1, 1);
string b = funs.Fun("2", "2");
string c = string.Format("{0},{1}", a, b);
Console.WriteLine(c);
Console.Read();
⌨⌨递归
- 方法自己调用自己
- 多个方法之间来回调用
- 使用递归时一定要有出口
- 使用递归时,一定概要慎重慎重再慎重…
⌨⌨⌨构造函数
- 执行的时机
- new对象()的时候调用
- 构造函数一般都是public
- 因为一旦构造函数被设置为了private,那么外界就无法new这个
- 构造函数没有返回值
- 也不能写返回值类型
- 构造函数的名字必须和类名保持完全的一致
- 构造函数是像普通方法一样被直接调用的
- 关于系统会不会自动创建一个空参空方法体的构造给你
- 如果一个类没有构造函数
- 那么系统会自动写一个空参数空方法体的构造函数
- 如果有构造函数
- 那么系统就不会帮你自动创建
- 如果一个类没有构造函数
- 构造函数可以有参、也可以无参
- 构造函数是可以重载的
- 如果想在执行当前构造函数之前,先执行其他的构造函数
- 当前构造函数(…)
- 如果想在执行当前构造函数之前,先执行其他的构造函数
class Person
{
private int age;
private string name;
public Person(int age)
{
this.age = age;
Console.WriteLine(age);
}
public Person(string name) : this(18)
{
this.name = name;
Console.WriteLine(name);
}
public Person(int age, string name) : this("xian")
{
Console.WriteLine("我是性别,年龄!");
}
}
static void Main(string[] args)
{
Person body = new Person(128, "alll");
Console.Read();
}
🍺🍺🍺多态
⌨关于父类空参数构造函数的调用说明
- 首先,先要明确一点
- 子类在声明构造函数的时候,要想办法调用父类的构造
- 如果父类是空参数的构造函数 : base()
- 可以不写:base()
- 系统会默认调用父类的空参数构造
- 如果父类是有参数的构造函数,那么一定概要通过:base的方式调用,
- 如果父类是空参数的构造函数 : base()
- 关于VS自动生成类构造函数
- 右键类名
- 点击快速修复或重构
- 点击生成构造
public class Person
{
public string name;
public Person(string name)
{
this.name = name;
Console.WriteLine(name);
}
public void Say()
{
Console.WriteLine("你在干什么!");
}
}
public class Person1:Person
{
public Person1(string name):base(name)
{
}
public new void Say()
{
Console.WriteLine("弄啥呢!");
}
}
public class Person2:Person1
{
public Person2(string name) : base(name)
{
}
public new void Say()
{
Console.WriteLine("搞啥呢!");
}
}
static void Main(string[] args)
{
Person p = new Person("1");
p.Say();
Person1 p1 = new Person1("2");
p1.Say();
Person2 p2 = new Person2("3");
p2.Say();
PersonFun(p2);
Console.ReadLine();
}
public static void PersonFun(Person person)
{
person.Say();
}
⌨子类方法的覆盖
- 前提条件:父类中有一个public函数,子类中没有该函数
- 因为子类中并没有该函数,所以调用必是父类的
- 前提条件:子类里已经有了该函数,父类里面也有该函数
- 此时,子类对象调用子类的该函数,父类对象调用父类的该函数
- 这种子类函数,可以称之为
- 子类在书写该函数的时候,规范的写法应该是:
- [访问修饰符] 返回值类型 函数名(参数列表)
- 覆盖:子类也有该函数了,以后调用的时候就调用子类的该函数
⌨子类方法的重写【表现出多态】
- 如果父类想要子类可以重写该函数
- 那么父类的该函数必须是一个虚函数
- [访问修饰符] 返回值类型 函数名(参数列表)
- 子类该怎么重写
- [访问修饰符] 返回值类型 函数名(参数列表)
- 重写:把子类和父类的该函数都重新写了一遍,有的新的内容
- 此时,子类的对象,无论是不是转换成了父类的类型,都会执行重写后的该函数
- 关于VS自动生成类重写函数
- 右键类名
- 点击快速修复或重构
- 点击生成重写
public class Person
{
public string name;
public Person()
{
}
public Person(string name)
{
this.name = name;
}
public virtual void Say()
{
Console.WriteLine("我是父类的方法");
}
}
public class Person1 : Person
{
public Person1(string name)
{
}
public override void Say()
{
Console.WriteLine("我是字类的方法");
}
}
static void Main(string[] args)
{
Person1 p1 = new Person1("我是字类");
p1.Say();
Person p = new Person1("我是父类");
p.Say();
Console.ReadLine();
}
⌨⌨所有类的最终基类:
- 所以,所有类都可以重写Object类中的虚方法
- Object的虚方法有三个:
- Equals:描述对象与对象之间是否相等
- GetHashCode:将一个对象编程一串数字
- ToString:将一个对象转换为一个字符串