C#基础到入门(一篇就够了)_c#怎么学

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

C#😀😀😀

✨文章有误请指正如果觉得对你有用请点赞收藏关注一波谢谢支持😘

提示以下是本篇文章正文内容

C#

简介

  1. C#是微软公司发布的一种由CC++衍生出来的面向对象的编程语言它不仅去掉了 C++ 和 Java 语言中的一些复杂特性还提供了可视化工具能够高效地编写程序。
  2. C#是由CC++衍生出来的一种安全的、稳定的、简单的、优雅的面向对象编程语言。它在继承CC++强大功能的同时去掉了一些它们的复杂特性例如没有宏以及不允许多重继承。
  3. C#使得C++程序员可以高效的开发程序且因可调用由 C/C++ 编写的本机原生函数而绝不损失C/C++原有的强大的功能。因为这种继承关系C#与C/C++具有极大的相似性熟悉类似语言的开发者可以很快的转向C#。

C#关键字

abstractdecimalfinallyinpartialshorttypeofvolatile
可以和类、方法、属性、索引器及事件一起使用标识一个可以扩展但不能被实体化的、必须被实现的类或方法。~定义一个代码块在程序控制离开try代码块后执行。参见try和catch。~~~一个操作符返回传入参数的类型。标识一个可被操作系统、某些硬件设备或并发线程修改的attribute。
asdefaultfixedintoutsetuintwhere
一个转换操作符如果转换失败就返回null。~在一个代码块执行时在固定内存位置为一个变量指派一个指针。~标识一个参数值会受影响的参数但在传入方法时该参数无需先初始化。~~~
basedelegatefloatinterfacenamespacestackallocuncheckedwhile
用于访问被派生类或构造中的同名成员隐藏的基类成员。指定一个声明为一种委托类型。委托把方法封装为可调用实体能在委托实体中调用。~将一个声明指定为接口类型即实现类或构造必须遵循的合同。定义一个逻辑组的类型和命名空间。返回在堆上分配的一个内存块的指针。禁止溢出检查。~
boolcontinueforinternaloverridesizeofulongyield
true/false~~一个访问修饰符。~一个操作符以byte为单位返回一个值类型的长度。~~
breakdoubleforeachisprivatestaticunsafeclass
终止循环语句~用于遍历一个群集的元素。~~~标注包含指针操作的代码块、方法或类。~
bytedogetlockrefthisvoidtrue
范围是0~255~~~标识一个参数值可能会受影响的参数。~~~
caseelsegotolongreadonlystructushortextern
~~一个跳转语句将程序执行重定向到一个标签语句。~标识一个变量的值在初始化后不可修改。是一种值类型可以声明常量、字段、方法、property、索引器、操作符、构造器和内嵌类型。~标识一个将在外部通常不是c#语言实现的方法。
catchenumifnewpublicthrowusingfalse
定义一个代码块在特定类型异常抛出时执行块内代码。表示一个已命名常量群集的值类型。~~~抛出一个异常。当用于命名空间时using关键字允许访问该命名空间中的类型而无需指定其全名。也用于定义finalization操作的范围。~
chareventimplicitnullreturntryvaluesbyte
~允许一个类或对象提供通知的成员他必须是委托类型。一个操作符定义一个用户定义的转换操作符通常用来将预定义类型转换为用户定义类型或反向操作隐式转换操作符必须在转换时使用。~~异常处理代码块的组成部分之一。try代码块包括可能会抛出异常的代码。参阅catch和finally关键字。~~
checkedexplicitconstobjectprotectedswitchvirtualsealed [18]
既是操作符又是语句确保编译器运行时检查整数类型操作或转换时出现的溢出。一个定义用户自定义转换操作符的操作符通常用来将内建类型转换为用户定义类型或反向操作必须再转换时调用显示转换操作符。标识一个可在编译时计算出来的变量值即一经指派不可修改的值。~~~一个方法修饰符标识可被覆载的方法。防止类型被派生防止方法和property被覆载。

🍺C#初次体验

⌨使用Visual Studio创建第一个项目 打印Hello world!

1.1 创建项目

打开VS->新键项目->找到控制台程序.NET Framework->下一步->创建
eg:
在这里插入图片描述

1.2 打印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 false 0000 0001 true
  • sbyte 有符号的8位整数 000 0000 — 111 1111 0-127
     1.第一位表示符号+ -
     2.特殊01000 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
    • int占4个字节面试经常问
  • long有符号的64位整数文档中是Int64
  • 浮点数通常理解就是生活中的小数
    • float单精度浮点数【文档中查Single】
      • 一般情况下float足够
    • double双精度浮点数【文档中查Double】
      • 如果需要精度更高一点用Double
    • decimal高精度浮点数
      • 极少用到天文数字可能会用到这个

⌨常量、变量

  • 程序运行期间
    • 程序开始到程序结束
  • 变量在程序运行期间可以被改变
    • 变量的声明
      • 数据类型 变量名 = 初值;
      • ⌨ 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❌
    • 不能与系统的关键词同名⌨ intlongsbyte❌
    • 变量名不能重复
    • 中文变量名语法上是可以的但极为不推荐
  • 常量及变量的命名规范
    • 全是英文单词不要用拼音
    • 驼峰命名法
      • 大驼峰每个单词的首字母大写其余字母小写
        • MyHeroDamage、HeroAttack
      • 小驼峰第一个单词首字母不大写后面每个单词的首字母大写其余字母小写
        • myHeroDamage、heroAttack【目前阶段都用小驼峰】
  • 见名知意
    • yyds你晓得这是啥评论区见❌

🍺运算符

⌨数据的量级

  • 赋值运算符 “=”是一个运算将后面的结果赋给前面的变量或常量
    • 前面 = 后面后面的值赋给前面
    • 前面必须是个变量【不能是具体是数值23’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=a+4; ==> a+=4;
  • 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.Read();
      • 从屏幕读取一个字符并返回该字符所对应的整型数字
    • Console.ReadLine();
      • 从屏幕读取一串字符并返回该字符串
      • 字符串是一个数据类型
        • 关键词string
        • 表示一串字符
        • 用双引号括起来
        • 字符串相加可以得到两个字符串组合到一起的字符串

📚预编译执行 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()
    • 其他类型能不能转换成字符串
      • 其他类型的变量.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初值为6number++ * ++number - number-- / --number
    • ②number初值为5number++ > 3 | --number == 0
    • ③number初值为2number-- > 2 && --number == 0
    • ④number初值为12number++ > 10 && --number != 2 && number-- == 0 && ++number != 3
    • ⑤number初值为0number++ > -1 || --number <= 2 && number-- != 10
    • ⑥number初值为0number++ < -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
      • 计算结果为6
  • 输入一个生日日期,输出其星座.
    白羊座: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…};
  • 静态初始化
    • 数据类型[] 数组名={元素1,元素2…};

🉑数组的访问

  • 0开始计数
  • 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}};

    • 静态初始化
      • 数据类型[,] 数组名 = {数组值};

        👂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关键词

在这里插入图片描述

🍺 字符串

ContainsContains
RemoveLastIndexOf
public string Remove( int startIndex/ int startIndex, int count )public int LastIndexOf( string/char value )
CopyToPadLeft
从 string 对象的指定位置开始复制指定数量的字符到 Unicode 字符数组中的指定位置。补充左边长度.PadLeft(2, ‘0’)
FormatPadRight
把指定字符串中一个或多个格式项替换为指定对象的字符串表示形式。补充右边长度.PadRight(2, ‘0’)
IndexOfReplace
返回指定 Unicode 字符在当前字符串中第一次出现的索引索引从 0 开始。替换文字stringObj.replace(“终古”,“中国”);
InsertSplit
返回一个新的字符串其中指定的字符串被插入在当前 string 对象的指定索引位置。返回一个字符串数组包含当前的 string 对象中的子字符串子字符串是使用指定的 Unicode 字符数组中的元素进行分隔的。
JoinToLower
连接一个字符串数组中的所有元素使用指定的分隔符分隔每个元素。把字符串转换为小写并返回。
SubstringToUpper
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这个
  • 构造函数没有返回值
    • 也不能写返回值类型
  • 构造函数的名字必须和类名保持完全的一致
  • 构造函数是不能像普通方法一样被直接调用的
  • 关于系统会不会自动创建一个空参空方法体的构造给你
    • 如果一个类没有构造函数
      • 那么系统会自动写一个空参数空方法体的构造函数
    • 如果有构造函数
      • 那么系统就不会帮你自动创建
  • 构造函数可以有参、也可以无参
  • 构造函数是可以重载的
    • 如果想在执行当前构造函数之前先执行其他的构造函数
      • 当前构造函数(…) : this(传实参)
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的方式调用传参
  • 关于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函数子类中没有该函数
    • 因为子类中并没有该函数所以调用必是父类的
  • 前提条件子类里已经有了该函数父类里面也有该函数
    • 此时子类对象调用子类的该函数父类对象调用父类的该函数
    • 这种子类函数可以称之为覆盖
    • 子类在书写该函数的时候规范的写法应该是
      • [访问修饰符] new 返回值类型 函数名(参数列表)
    • 覆盖子类也有该函数了以后调用的时候就调用子类的该函数

在这里插入图片描述

子类方法的重写【表现出多态】

  • 如果父类想要子类可以重写该函数
    • 那么父类的该函数必须是一个虚函数
    • [访问修饰符] virtual 返回值类型 函数名(参数列表)
  • 子类该怎么重写
    • [访问修饰符] override 返回值类型 函数名(参数列表)
  • 重写把子类和父类的该函数都重新写了一遍有的新的内容
    • 此时子类的对象无论是不是转换成了父类的类型都会执行重写后的该函数
  • 关于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类中的虚方法
  • Object的虚方法有三个
    • Equals描述对象与对象之间是否相等
    • GetHashCode将一个对象编程一串数字
    • ToString将一个对象转换为一个字符串

在这里插入图片描述

⌨⌨抽象方法

  • 抽象方法的关键词abstruct
    • abstruct 返回值类型(参数列表)
  • 抽象方法必须要放在抽象类里面
  • 抽象方法没有方法体 [访问修饰符] abstruct 返回值类型 方法名(形参列表);
  • 抽象方法的访问修饰符不能是private
  • 抽象类即可以放抽象方法也可以放普通方法
  • 抽象方法必须在子类中全部实现
    • 除非子类也是一个抽象类那么可以先不实现该抽象方法
  • 抽象方法和虚方法最大的区别
    • 抽象方法必须其派生类中得以实现
    • 而虚方法不是一定要在其派生类去重写
  • 无论是虚方法还是抽象方法子类进行了重写【实现】
    • 那么子类的子类依旧可以继续重写
  • 抽象类不能sealed关键词修饰
  • 总结override可以重写哪些方法呢
    • 带有virtual、abstruct、override关键词的方法

代码

//抽象类
public abstract class Person
{
    public void Fun(string name)
    {
        Console.WriteLine(name);
    }
    public abstract void Say();
}
public class Person1 : Person
{
    public override void Say()
    {
        Console.WriteLine("asd");
    }
}
static void Main(string[] args)
{

    Person1 a = new Person1();
    a.Say();
    Console.Read();
}

⌨⌨sealed关键词

  • 密封类
    • sealed关键词修饰的类称之为密封类
    • 语法sealed class 类名
    • 密封类是不能被别的类继承的
  • 密封方法
    • sealed关键词修饰的重写的方法称之为密封方法
    • 语法sealed override 返回值类型 方法名参数列表
    • 密封方法无法再次被其子类重写

代码

public class Person
{
public virtual void Fun()
{
  Console.WriteLine(1);
}
}
public class Person1 : Person
{
public sealed override void Fun()
{
  Console.WriteLine(2);
}
}
public class Person2 : Person1
{
//这里报错 因为续承的Person1是密封函数
public override void Fun()
{
  base.Fun();
}
}
static void Main(string[] args)
{

Person a = new Person1();
a.Fun();

Console.Read();

}

⌨⌨静态类

  • 关键词 static
  • 静态成员
    • 成员字段、属性、方法
    • 静态跟对象没有任何关系只跟类有关系
  • 静态成员在何时开辟的内存
    • 第一次访问这个类的时候【第一次用到这个类的时候】
      • 比如用这个类名去实例化一个对象
      • 比如用这个类型去访问一个静态字段
  • 静态成员在何时释放内存
    • 程序结束的时候才会释放
  • 普通的实例成员每有一个对象就有一个该成员
    • 而静态成员跟对象没有关系所以无论有多少个对象静态成员都只有一个
    • : 实例成员【name】,每有一个人就会有对应的一个名字
      • 而静态成员【Population】,跟对象没有关系无论有多少个实例对象人口数量只有一个
  • 静态方法中是不可以访问非静态的成员的
    • 不能访问非静态的字段、属性
    • 不能调用非静态的方法
  • 非静态方法中是可以访问静态成员的
    • 能访问静态的字段、属性
    • 能调用静态的方法
  • 静态方法是可以有重载
  • 静态类
    • 静态的成员可以放在静态类也可以放在非静态类
    • 静态类中只能存在静态成员不能存在非静态的成员
    • 静态类是不能进行实例化
  • 静态构造函数
    • 只有一种写法
      • static 类名()
    • 静态构造函数必须无参数
    • 静态构造函数在什么时候才会调用
      • 静态构造函数在程序运行期间只会执行一次
      • 在第一次访问该类的时候调用
        • 用这个类去new一个对象
        • 用这个类去访问某个静态成员
        • 用这个类去调用某个静态方法
    • 如果有继承关系
      • 静态构造函数的执行顺序是
      • 先执行子类的静态构造再执行父类的静态构造
      • 先子后父
    • 静态构造有什么作用
      • 一般用于对静态成员进行初始化

代码

class Person
{
    public static float age=88;
    public static void Fun()
    {
        Console.WriteLine("我是父静态类");
    }
    static Person()
    {
        Console.WriteLine("我是基静态类");
    }
}

class Per : Person
{
    static Per()
    {
        Console.WriteLine("我是子静态类");
    }
}
static void Main(string[] args)
{
    Per p = new Per();
    Console.WriteLine();
    Console.ReadLine();
}

在这里插入图片描述

集合、栈、堆、队列、字典 ✍🔤🔤🔤

1、集合~范型命名空间using System.Collections.Generic;

1.1、ArrayList

代码

//实例化动态数组
ArrayList score = new ArrayList();
//向动态数组中添加元素
score.Add(90);
score.Add(85.5f);
score.Add("English:100");

int[] array = { 90,80,70 };
//向动态数组中批量添加元素
score.AddRange(array);
//向动态数组中插入元素
score.Insert(2, "Math:80.5");
//删除动态数组中的元素
score.Remove(85.5f);
//删除的是单个约束如果动态数组中没有该元素就忽略
score.Remove(90);
//根据下标移除动态数组中的元素
score.RemoveAt(0);

score.AddRange(new string[] { "A", "B", "C", "A" });
//批量删除元素
score.RemoveRange(2, 3);
//如果数组中没有该下标所对应的元素则也会出现越界异常
Console.WriteLine(score[1]);
//数组元素翻转
score.Reverse();	
//一般想要删除某个元素会先进行判断是否存在
bool containsA = score.Contains("A");
Console.WriteLine("containsA:" + containsA);
//判断数组中是否包含某个元素
if(score.Contains("A"))
{
  score.Remove("A");
}
Console.WriteLine("Count:" + score.Count);
//给一个元素的值查该值在动态数组中的下标
Console.WriteLine("IndexOf:" + score.IndexOf(790));
score.Clear();

score.AddRange(new float[] { 1.1f,5.7f,4.5f,9.8f,3,2,1});
//从小到大排序
score.Sort();
//清空动态数组
//score.Clear();
Console.WriteLine("-------------");
for (int i = 0; i < score.Count; i++)
{
  Console.WriteLine(score[i]);
}
Console.WriteLine("-------------");
foreach (var item in score)
{
  Console.WriteLine(item);
}

1.2、List

代码

//初始化范型集合
List<int> list = new List<int>();

//添加元素
list.Add(200);
list.Add(250);
list.Add(280);
//批量添加元素
list.AddRange(new int[] { 1,3,5,6,7,9 });
//移除某个元素
list.Remove(280);
//通过下标移除某个元素
list.RemoveAt(0);
list.RemoveAt(0);
//批量删除
list.RemoveRange(0, 3);
int index = list.IndexOf(9);
Console.WriteLine(index);
Console.WriteLine("-----------");
foreach (var item in list)
{
   Console.WriteLine(item);
}

2、栈Stack

  • 说明后进先出

代码
eg:非范型为例😥

Object<=Stack stack = new Stack();
//进栈
stack.Push("我是第一个进去的");
stack.Push("我是第二个进去的");
stack.Push("我是第三个进去的");
//出栈
Console.WriteLine(stack.Pop());
Console.WriteLine(stack.Pop());
Console.WriteLine(stack.Pop());
Console.Read();
//返回栈顶的元素Peek();

在这里插入图片描述

  • 常用方法
    在这里插入图片描述
  • Stack.TryPeek(T) 方法
  1. 返回一个值该值指示 Stack 的顶部是否有对象如果有则将其复制到 result 参数。 不从 Stack 中删除对象。
  2. public bool TryPeek (out T result);
  3. 返回
    Boolean
    如果 Stack 的顶部有对象则为 true如果 Stack 为空则为 false。
  • Stack.TryPop(T) 方法
  1. public bool TryPop (out T result);
  2. 返回一个值该值指示 Stack 的顶部是否有对象如果有则将其复制到 result 参数并从 Stack 中删除它。
  3. 返回
    Boolean
    如果 Stack 的顶部有对象则为 true如果 Stack 为空则为 false。

3、堆heaps

😀😀😀略略略

4、队列Queue

  • 说明先进先出
    eg进列
    在这里插入图片描述
    eg出列
    在这里插入图片描述
    代码
    eg:非范型为例😥
Queue queue = new Queue();
//进列
queue.Enqueue("我是第一个进去的");
queue.Enqueue("我是第二个进去的");
queue.Enqueue("我是第三个进去的");
//出列
Console.WriteLine(queue.Dequeue());
Console.WriteLine(queue.Dequeue());
Console.WriteLine(queue.Dequeue());
Console.Read();

在这里插入图片描述
常用方法:

在这里插入图片描述

5、字典Dictionary<string,int>

在这里插入图片描述
代码

Dictionary<string, int> dis = new Dictionary<string, int>();
dis.Add("我是第一个进去的", 1);
dis.Add("我是第二个进去的", 2);
dis.Add("我是第三个进去的", 3);
Console.WriteLine(dis.Values);
Console.WriteLine(dis.ContainsValue(2));
Console.WriteLine(dis.ContainsValue(3));
Console.Read();

6、常见的接口

在这里插入图片描述

🍺🍺🍺🍺单例、接口和范型

1、单例

  • 如果一个对象在声明时直接实例化【new】。
  • 在访问这个类的时候调用
  • 实例化的时间点最早在静态构造之前就执行了

在这里插入图片描述

2、接口

  • 接口相比类最大的不同之处在于只有定义没有实现
  • 接口相当于一堆骨架实现接口的类用于填充骨架上的肉
  • 接口不能进行实例化只能被类或其他接口实现
  • 如即继承类又实现接口时类要放在最前面接口放在后面
    eg:
    • class Person1:Person,jiankou1,jiekou2

在这里插入图片描述

2.1、接口和抽象类的对比

  • 相同点
    • 两者都不能被实例化
    • 两者都包含了由其他类或结构继承或实现的抽象成员不同点
  • 不同点
    • 抽象类当中除了拥有抽象成员外还可以拥有非抽象成员而接口中所有的所有成员都是抽象的
    • 抽象成员可以使用修饰符修饰接口当中接口成员访问级别是默认不可修改的并且默认是public
    • 接口当中不可以包含构造方法析构方法静态成员以及常量
    • C#类只支持单继承接口支持多支持

3、范型

  • 范型类的构造函数不用写范型类
  • 有些时候重载的方法只有参数类型不同其他的都一样这时就可以使用泛型。
  • 泛型需要用户自己传过来的一个数据类型
  • 平时方法里传递的是参数是变量参数传递用的是小括号。
    而泛型传递的是数据类型泛型传递用的尖括号<>
  • 泛型定义之后一定要用不然就没有意义
    • 泛型都在方法的哪里用
      • 定义参数
      • 在方法体呢使用泛型定义局部变量口
      • 设置返回值类型是一个泛型。给泛型添加约束
  • 给范型舔加约束
    • 方法名参数列表where 泛型约束内容
    • 方法名参数列表where 泛型A约束内容1约束内容2 where 泛型B约束内容3
  • 关于泛型方法的重载
    • 如果泛型的个数不同可以重载
    • 如果泛型的个数相同但约束不同不可以重载
  • 关于泛型类和泛型接口
    • class 类名<T,F>
      • 类中的字段类型、方法参数、方法返回值都可以使用类中的泛型
    • interface 接口名< T >
      在这里插入图片描述

代码

public class fanxing
{
  
}
public static void FX<T>(T sex, T age)
{
   T temp = sex;
   sex = age;
   age = temp;
   Console.WriteLine(age);
}
public static void FX<T>(T sex, T age, T a)
{
   T temp = sex;
   sex = age;
   age = temp;
   Console.WriteLine(age);
}

static void Main(string[] args)
{
  FX<int>(7,8);
  FX<float>(7,8);
   Console.ReadLine();
}
- 范型方法的范型重载
eg 代码
```代码
public static void faning<T>()
{

}
public static void faning<T,F>()
{

}
public static void faning<T,F,U>()
{

}

static void Main(string[] args)
{
   faning<>

}

在这里插入图片描述

🍺🍺🍺🍺委托与事件

1、委托delegate

2.1常见委托类型

  • 什么是委托相当于中介
  • 委托的别名代理、句柄
  • 委托是自定义类型
  • 委托是引用类型

代码eg
eg:非范型为例😥

//定义委托
delegate void weituo(float momey);
class p1
{
	public void zhao1(float momey)
    {
		Console.WriteLine("中介一需要:"+momey+"$");
    }
	public void zhao2(float momey)
	{
		Console.WriteLine("中介二需要:"+ momey + "$");
	}
	public void zhao3(float momey)
	{
		Console.WriteLine("中介三需要:"+ momey + "$");
	}
	public void zhao4(float momey)
	{
		Console.WriteLine("中介四需要:"+momey + "$");
	}
}

internal class Program
{
	static void Main(string[] args)
	{
		p1 p = new p1();

		weituo we;

		we = p.zhao1;
		we += p.zhao2;
		we += p.zhao3;
		we += p.zhao4;
		we(1232143);
		Console.Read();
	
	}
}

2.2系统委托类型

  1. 无返回值系统委托 Action<>

代码eg
eg:😥

class p1
{
	public void wcs()
	{
		Console.WriteLine("我是无参数的中介需要:" + "18456456456456"+ "$");
	}
	public void zhao1(float momey)
    {
		Console.WriteLine("中介一需要:"+momey+"$");
    }
	public void zhao2(float momey)
	{
		Console.WriteLine("中介二需要:"+ momey + "$");
	}
	public void zhao3(float momey)
	{
		Console.WriteLine("中介三需要:"+ momey + "$");
	}
	public void zhao4(float momey)
	{
		Console.WriteLine("中介四需要:"+momey + "$");
	}
}

internal class Program
{
	static void Main(string[] args)
	{
		p1 p = new p1();
		//使用系统委托
		//无参数
		Action action;
		action = p.wcs;
		action();

		//参数
		Action<float> action1;
		action1 = p.zhao1;
		action1 += p.zhao2;
		action1 += p.zhao3;
		action1 += p.zhao4;
		action1(182);
		Console.Read();
	}
}

在这里插入图片描述

  1. 有返回值系统委托 Func<>

代码eg
eg:😥

class Hout
{

}
class p1
{
	public string Func1()
	{
		return "有返回值函数无参数:";
	}

	public Hout Func2(string name)
	{
		Console.WriteLine("有返回值函数有参数:"+name);
		return null;
	}

}

internal class Program
{
	static void Main(string[] args)
	{
		p1 p = new p1();

		Func<string> func;

		func = p.Func1;

		Console.WriteLine(func());


		Func<string,Hout> func1;

		func1 = p.Func2;

		Hout a= func1("先生");

		Console.Read();
	}
}

在这里插入图片描述

2.3委托之匿名函数

代码eg
eg:😥

class p1
{
	public Action<string> action;
	public string name;
	public int age;

    public p1(string name, int age)
    {
        this.name = name;
        this.age = age;
    }

	public void isAction(string age)
    {
        Console.WriteLine("我是个中介:"+ age);
        if (action != null)
        {
            action(age);
            Console.WriteLine("我是个中介:" + age);
        }
    }
}

internal class Program
{
	static void Main(string[] args)
	{
        p1 p = new p1("先生",18);

        p.action = delegate (string a)
        {
            Console.WriteLine(a);
            Console.WriteLine("我好蒙啊2");
        };
        p.action += read;

        p.isAction("我好蒙啊1");

        Console.Read();
	}
    public static void read(string name)
    {
        Console.WriteLine(name);
        Console.BackgroundColor = ConsoleColor.Red;
        Console.ForegroundColor = ConsoleColor.Black;
    }
}

❌❌❌如何使用VS进行程序调试

  • 程序是从Main函数开始顺序执行的
  • 调试就是在你觉得可能会发生问题的地方打下断点
    • 什么是断点
      • 让程序执行到这个地方暂停下来的点
    • 有什么好处可以一句句或一段段让程序执行
  • 调试步骤
    • 给想要暂停的代码行添加断点
    • 开始调试
    • 通过监视或局部变量窗口去看此时你想观察的变量的值
    • 如果想看变量or对象的内存地址
      • 找到即时窗口
      • &变量名

在这里插入图片描述

总结

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

“C#基础到入门(一篇就够了)_c#怎么学” 的相关文章