C#精通
本文章主要是对于学习C#基础难点进行学习以及与java语言的不同点,详细学习可见官网:https://dotnet.microsoft.com/en-us/learn
文章目录
- C#精通
- VS
- VS基本设置
- C#是什么
- C#程序
- 控制台输出
- 变量内插
- 占位符
- C#foreach循环
- 类型转换
- 操作数组
- 内置方法
- 格式设置
- 方法
- 复杂类型
- 枚举类型
- 飞行棋小项目
- 面向对象
- 属性
- 构造函数,this关键字
- 析构函数
- 命名空间
- 引用其他项目
- 值类型和引用类型
- 构造方法
- 里氏转换
- 集合
- 数组和集合的转换
- Hashtable
- 字典(Dictionary)
- File
- Directroy(文件夹操作类)
- Path(文件路径操作类)
- 读写数据
- 文件流
- FileStream(字节操作)
- 读
- 写
- StreaReader和StreamWriter
- 读
- 写
- 多态实现形式
- 虚方法
- 抽象类
- 序列化和反序列化
- 密封部分类
- MD5加密
VS
- 安装VS,目录:解决方案>项目>类 可在方案中创建多个项目。
VS基本设置
- 生成->生成解决方案 可排查错误
- 工具->选项 可设置字体,行号
- vs默认启动第一项目,右击解决方案->属性可自选
- 快捷键
ctrl+k+d:快速对齐 ctrl+j:提示 shift+alt+f10:生成解决方案 ctrl+alt+x:打开工具箱
- 折叠代码
C#是什么
C#(发音为 “C Sharp”)是一种现代、面向对象的、类型安全的编程语言,由微软开发,首次发布于2000年。C#的设计者是Anders Hejlsberg,他也是Turbo Pascal和Delphi的创造者。C#结合了C++的强大特性和Visual Basic的易用性,旨在提供一种新的编程语言,以适应.NET框架的需要。
语法和Java很类似
C#程序
控制台输出
每个语言都有控制台输出,如java中的println
> 逐字字符串文本将保留所有空格和字符,而无需转义反斜杠。
要创建逐字字符串,请在文本字符串的前面使用 @ 指令。
```java
C# 不换行输出Console.Write()换行输出Console.WriteLine()
如需原封不动输出Console.Write(@"hsfdsj dfjkslfjdsklf kdfj \\\ n ");
```
- Console.ReadKey();等待用户按下任意键 参数为true不显示控制台
- Console.ReadLine();接受用户输入 相当于java new Scanner(System…).next()
- 控制台前景色:Console.ForegroundColor = ConsoleColor.Red;
- Console.Clear():清空控制台
变量内插
若要将两个字符串内插在一起,请创建一个文本字符串,并在字符串前面加上 $ 符号。 文本字符串应包含至少一组大括号 {},且你会在这些字符内使用变量的名称。
```javapublic static void test2(){var firstName = "张三";String a = $"hello {firstName}";Console.Write($"{a}");}
```
`@和$可联合使用````javapublic static void test2(){var firstName = "张三";String a = @$"hello {firstName}豆瓣 111";Console.Write($"{a}");}
```
占位符
Console.WriteLine(“{0}sdlfsjlf”,变量);变量可占据0这个位置,多个变量,只需要增加数值就行。
C#foreach循环
```javaforeach(String s in str){if (s.StartsWith("B")){Console.WriteLine($"嫌疑{s}");}}//java for(String s : str){}
```
类型转换
使用 Convert.ToInt32() 进行转换时,文本浮点数值将正确地向上舍入到 2。 如果你将文本值更改为 1.499m,则会向下舍入到 1。
int atos = 11;String num = "22";String f = "1";int res1 = int.Parse(num)*atos;String res2 = Convert.ToString(atos);Console.WriteLine(@$"类型:{res1.GetType().Name} 值:{res1}"); Console.WriteLine(@$"类型:{res2.GetType().Name} 值:{res2}");Console.WriteLine(Convert.ToInt32(1.5f));
//类型:Int32 值:242
//类型:String 值:11
//2
-
判断转换
对于字符串转换成int类型,如不是数值问题就会转换失败,我们可以使用TryParse()来判断
out 参数提供了返回值的方法的辅助手段。 在这种情况下,out 参数返回转换后的值public static void test1(){String str1 = "11ab";String str2 = "22";int result = 0;if (int.TryParse(str2,out result)){Console.WriteLine("转换成功==》" + result);}else{Console.WriteLine("转换失败");}}
操作数组
-
数组
Array.sort();//排序 Array.reverse();//反转 Array.clear();//删除 Array.resize();//改变大小 ... 这些方法和java个别是有差异的
内置方法
- indexof() ,LastIndexOf(),IndexOfAny()
- remove(),replace()
格式设置
方法
-
out参数
当一个方法需要返回多个不同类型的返回值时,可以使用out作为返回参数。一旦定义了out返回参数,就需要在方法内赋值。方法外需要定义接受,名字可不同。
static void Main(string[] args){int[] nums = { 4, 2, 1, 9 };string name1;nums = getNumsRef(nums, out name1);Console.WriteLine(name1);Console.WriteLine($"最大值={nums[1]},最小值={nums[0]}");}/// <summary>/// out 参数练习/// </summary>/// <param name="nums">数组</param>/// <param name="name">返回参数</param>/// <returns>求最大值,最小值</returns>public static int[] getNumsRef(int[] nums, out string name){name = "返回最大最小的方法名";Array.Sort(nums);int[] refs = new int[2];refs[0] = nums[0];refs[1] = nums[nums.Length-1];return refs;}
-
ref 参数
引用外部变量,可以将外部变量带入方法内部,然后再带出方法外部。要求方法外部必须定义赋值
static void Main(string[] args){int num = 10;addMoney(ref num);Console.WriteLine(@"加完之后的值:{0}",num);//110}public static void addMoney(ref int num){num += 100;}
-
命名参数:生命参数,以改变参数位置
public static void test6(){method1(age:11,name: "zhangsan");}public static void method1(String name,int age){Console.WriteLine($"名字:{name},年龄:{age}");}
-
可变参数params
一个方法参数列表中只能出现一个可变参数,用户接受多个参数封装到一个数组中,且可变参数的位置必须是最后,才不会出现歧义。
static void Main(string[] args){countArrNum("长度", 3, 4, 56, 10);}public static void countArrNum(string name,params int[] num){Console.WriteLine(name+"->"+num.Length);}
-
声明参数:初始化参数值
public static void test6(){method1("lishi222");}public static void method1(String name="lisi",int age=1){Console.WriteLine($"名字:{name},年龄:{age}");}
复杂类型
- const 修饰 是常量
枚举类型
-
枚举类型转换成int
namespace Test2 {public enum SEASON{spring,summer=5,autumn,winter}class Program{static void Main(string[] args){#region 枚举类型转换成intSEASON s1 = SEASON.autumn;Console.WriteLine((int)s1);#endregion}} }
-
int转换成枚举
-
string转成成枚举
飞行棋小项目
- 飞行棋小项目 中的FlyGame项目
面向对象
属性
-
get和set方法简写
namespace _2024_0719_Project {class Person{private string _name;//字段private int _age;public string Name//属性{get { return _name; }set { _name = value; }}public int Age{get { return _age; }set { _age = value; }}public void speak(){Console.WriteLine("my name is {0},my age is {1}", this.Name, this.Age);}} }
c#中age为字段,Age为属性,当调用属性时会调用里面的get,set方法。
static void Main(string[] args){Person p = new Person();p.Age = 11;p.Name = "zhangsan";p.speak(); //my name is zhangsan,my age is 11 }
构造函数,this关键字
一个类是有默认的构造函数,如果你在类中定义了构造函数,则默认的构造函数 就不复存在。构造函数调用本类的构造函数可以使用this关键字
class Student{private string name;//main函数调用这个构造方法Student s = new Student("李四");public Student(string name):this("张三",11){this.Name = name;Console.WriteLine("名字: {0} 年龄: {1}",Name,Age);//名字: 李四 年龄: 11}private int age;public Student(string name,int age){this.Name = name;this.Age = age;}public Student(){}public string Name { get => name; set => name = value; }public int Age { get => age; set => age = value; }}
可以看到,先执行this的构造函数,然后执行本构造函数
析构函数
析构函数程序结束执行,类中定义如下
~Student(){Console.WriteLine("我是析构函数");Console.ReadKey();}
命名空间
引用其他项目
- 引用其他项目:1.在项目依赖项中右击,选择添加项目引用 2.使用using 命名空间
值类型和引用类型
值类型:int double decimal struct enum…
引用:数组 类 string
构造方法
-
子类继承父类 : 子类:父类
-
子类继承不了父类的私有
-
子类继承父类,可以访问父类的共有的属性,字段,方法
当调用子类的无参构造方法,首先是创建父类,调用父类的构造方法(如果父类中定义了有参构造方法,则必须定义父类无参构造方法以便创建)
子类为什么能访问父类的方法,肯定是提前创建了父类对象。class Program{static void Main(string[] args){Stu stu = new Stu("张三", 11);stu.CommonWalk();Console.WriteLine(stu.Name);}}public class Person{private string personName;private string name;public int age;public Person(string name, int age){this.name = name;this.age = age;}public int Age { get => age; set => age = value; }public string Name { get => name; set => name = value; }public void CommonWalk(){Console.WriteLine("通用方法");Console.ReadKey();}}//继承public class Stu : Person{private string name;public int age;//显示调用父类有参构造方法创建父类对象public Stu(string name, int age) : base(name, age){}public string Name1 { get => name; set => name = value; }}
控制台打印:
通用方法
张三
里氏转换
-
子类可以赋值给父类;父类可以强转成其子类;
-
is 关键字判断是否是此类型
static void Main(string[] args){Person[] person = new Person[2];person[0] = new Stu();if(person[0] is Stu){person[0].pSpeak();//父类只可以调用自己的Stu stu = (Stu)person[0];stu.stuSpeak();}}
集合
- Add 添加单个 AddRange添加多个
- Clear清空所有元素 Remove 删除单个 RemoveAt根据下标删除 RemoveRange:根据下标移除范围内的元素
- Sort 比较排序 Rerverse 反转
- Insert:在指定位置插入元素 InsertRange
- Contains 判断是否包含
- count 实际包含长度 capacity 可包含长度
数组和集合的转换
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;namespace _5_Project
{class Program{static void Main(string[] args){List<int> list = new List<int>();list.Add(1);list.Add(2);int[] arr = list.ToArray();//list 转数组list = arr.ToList();//数组转listforeach (var de in list){Console.Write(de + " ");}}}
}
Hashtable
Hashtable hashtable = new Hashtable();hashtable.Add(1, "张三");hashtable.Add(false, "李四");foreach(var key in hashtable.Keys){Console.WriteLine($@"key:{key} value {hashtable[key]}");}
字典(Dictionary)
-
适合定义泛型
static void Main(string[] args){Dictionary<int, string> dic = new Dictionary<int, string>();dic.Add(1, "张撒");dic.Add(2, "李四");foreach (KeyValuePair<int,string> kv in dic){Console.WriteLine(@$"键---{kv.Key},值---{kv.Value}");}}
File
Directroy(文件夹操作类)
- CreateDirectory:创建文件夹
- Delete:删除文件夹
- Move:剪切文件夹
- GetFiles:获取指定文件下所有文件的全路径,重载可筛选文件*.jpg
- Exist:判断文件夹是否存在
Path(文件路径操作类)
static void Main(string[] args){string p = @"D:\周报\周周报.xlsx";Console.WriteLine("文件名包括扩展 {0}",Path.GetFileName(p));Console.WriteLine("文件名不包括扩展 {0}", Path.GetFileNameWithoutExtension(p));Console.WriteLine("获取扩展名 {0}", Path.GetExtension(p));Console.WriteLine("获取文件所在文件夹 {0}", Path.GetDirectoryName(p));Console.WriteLine("获取全路径 {0}", Path.GetFullPath(p));}
- File.Create File.Delete File.Copy File.Move … 网上搜相关方法
读写数据
-
读 ReadAllBytes:有注释
-
写:WriteAllBytes
//获取字符串的字节byte[] buff = Encoding.GetEncoding("UTF-8").GetBytes("你好酒店房间打开,d");File.WriteAllBytes(@"E:\测试\a.txt",buff);//写入指定路径Console.WriteLine("写入成功");
File还有很多好用的方法,可查API
文件流
File由于是一次操作文件,对性能消耗比较大
FileStream(字节操作)
读
//创建流,打开或创建,可读权限FileStream fileStream = new FileStream(@"E:\测试\aa.txt",FileMode.OpenOrCreate,FileAccess.Read);byte[] buff = new byte[1024];int r = fileStream.Read(buff,0,buff.Length);//返回读到的位置,读多少个string msg = Encoding.GetEncoding("UTF-8").GetString(buff, 0, r);//关闭fileStream.Close();fileStream.Dispose();Console.WriteLine(msg);
写
//写//using框架会帮我们自动关闭流资源using (FileStream fileStream1 = new FileStream(@"E:\测试\aa.txt", FileMode.Append, FileAccess.Write)){byte[] buff1 = Encoding.UTF8.GetBytes("我是写入的数据");fileStream1.Write(buff1, 0, buff1.Length);Console.WriteLine("写入成功");}
StreaReader和StreamWriter
读
//读using (StreamReader streamReader = new StreamReader(@"E:\测试\aa.txt", Encoding.UTF8)){while (!streamReader.EndOfStream){string str = streamReader.ReadLine();Console.WriteLine(str);}}
写
//写,true为追加using (StreamWriter streamWriter = new StreamWriter(@"E:\测试\b.txt",true)){streamWriter.WriteLine("这是我写的");Console.WriteLine("写完了");}
多态实现形式
虚方法
在子类要重写的方法的父类中用virtual关键字修饰,子类的方法用override修饰
using System;namespace _9_Project
{class Program{static void Main(string[] args){Person p1 = new Stu();p1.speak();//可以看到这里不调用父类的方法,而是子类的}}class Person{public virtual void speak(){Console.WriteLine("我是人类");}}class Stu : Person{public override void speak(){Console.WriteLine("我是子类学生");}}
}
抽象类
序列化和反序列化
-
在类的上一行[Serializable] 表示可序列化
//序列化Person p = new Person("张三",11);using (FileStream writer =new FileStream(@"E:\测试\c.txt",FileMode.OpenOrCreate,FileAccess.Write)){BinaryFormatter binaryFormat = new BinaryFormatter();binaryFormat.Serialize(writer, p);}//反序列化using(FileStream reader = new FileStream(@"E:\测试\c.txt", FileMode.OpenOrCreate, FileAccess.Read)){BinaryFormatter binaryFormat = new BinaryFormatter();Person p2 = (Person)binaryFormat.Deserialize(reader);Console.WriteLine($@"名字=》{p2.Name} 年龄=>{p2.Age}");}
密封部分类
- 使用sealed修饰类,表示此类不可被继承
- 使用partial修饰类,表示此类是部分类,几个部分类共享彼此的数据
MD5加密
static void Main(string[] args){MD5 md5 = MD5.Create();String str = "我是加密的字符串";byte[] buff1 = Encoding.UTF8.GetBytes(str);buff1= md5.ComputeHash(buff1);string append = "";for(int i = 0; i < buff1.Length; i++){append += buff1[i].ToString("x");//转换16进制}Console.WriteLine(append.ToString());}