🍺 字符串
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命名空间下
- 所以使用时,需要先引入这个命名空间
usingSystem.Text;
- 如果不引入,可以直接写:
System.Text.StringBuilderstrB=newSystem.Text.StringBuilder();
- 使用时,先要new
StringBuilderstringB=newStringBuilder();
- 追加字符串
//追加字符串stringBuilder.Append("天气好晴朗");
- 什么时候用StringBuilder而不用string
- 字符串需要经常修改的时候
⌨⌨⌨方法的重载
- 同一个类里面,方法名一样,但参数不一样
- 参数的数据类型不一样
- 参数的个数不一样
- 参数的数据类型不一样,个数也不一样
- 参数个数和类型都一样,但返回值类型不一样,不能算做重载❌
classFuns{ publicstringFun(stringa, stringb) { return"a+b"; } publicintFun(inta, intb) { returna+b; } } Funsfuns=newFuns(); inta=funs.Fun(1, 1); stringb=funs.Fun("2", "2"); stringc=string.Format("{0},{1}", a, b); Console.WriteLine(c); Console.Read();
⌨⌨递归
- 方法自己调用自己
- 多个方法之间来回调用
- 使用递归时一定要有出口
- 使用递归时,一定概要慎重慎重再慎重…
⌨⌨⌨构造函数
执行的时机
new对象()的时候调用
构造函数一般都是public
因为一旦构造函数被设置为了private,那么外界就无法new这个
构造函数没有返回值
也不能写返回值类型
构造函数的名字必须和类名保持完全的一致
构造函数是不能像普通方法一样被直接调用的
关于系统会不会自动创建一个空参空方法体的构造给你
如果一个类没有构造函数
那么系统会自动写一个空参数空方法体的构造函数
如果有构造函数
那么系统就不会帮你自动创建
构造函数可以有参、也可以无参
构造函数是可以重载的
如果想在执行当前构造函数之前,先执行其他的构造函数
当前构造函数(…) : this(传实参)
classPerson{ privateintage; privatestringname; publicPerson(intage) { this.age=age; Console.WriteLine(age); } publicPerson(stringname) : this(18) { this.name=name; Console.WriteLine(name); } publicPerson(intage, stringname) : this("xian") { Console.WriteLine("我是性别,年龄!"); } } staticvoidMain(string[] args) { Personbody=newPerson(128, "alll"); Console.Read(); }
🍺🍺🍺多态
⌨关于父类空参数构造函数的调用说明
首先,先要明确一点
子类在实例化的时候,必会调用父类的构造函数
子类在声明构造函数的时候,要想办法调用父类的构造
如果父类是空参数的构造函数 : base()
可以不写:base()
系统会默认调用父类的空参数构造
如果父类是有参数的构造函数,那么一定概要通过:base的方式调用,传参
关于VS自动生成类构造函数
右键类名
点击快速修复或重构
点击生成构造
publicclassPerson{ publicstringname; publicPerson(stringname) { this.name=name; Console.WriteLine(name); } publicvoidSay() { Console.WriteLine("你在干什么!"); } } publicclassPerson1:Person{ publicPerson1(stringname):base(name) { } publicnewvoidSay() { Console.WriteLine("弄啥呢!"); } } publicclassPerson2:Person1{ publicPerson2(stringname) : base(name) { } publicnewvoidSay() { Console.WriteLine("搞啥呢!"); } } staticvoidMain(string[] args) { Personp=newPerson("1"); p.Say(); Person1p1=newPerson1("2"); p1.Say(); Person2p2=newPerson2("3"); p2.Say(); PersonFun(p2); Console.ReadLine(); } publicstaticvoidPersonFun(Personperson) { person.Say(); }
⌨子类方法的覆盖
前提条件:父类中有一个public函数,子类中没有该函数
因为子类中并没有该函数,所以调用必是父类的
前提条件:子类里已经有了该函数,父类里面也有该函数
此时,子类对象调用子类的该函数,父类对象调用父类的该函数
这种子类函数,可以称之为覆盖
子类在书写该函数的时候,规范的写法应该是:
[访问修饰符] new 返回值类型 函数名(参数列表)
覆盖:子类也有该函数了,以后调用的时候就调用子类的该函数
⌨子类方法的重写【表现出多态】
那么父类的该函数必须是一个虚函数
[访问修饰符] virtual 返回值类型 函数名(参数列表)
子类该怎么重写
[访问修饰符] override 返回值类型 函数名(参数列表)
重写:把子类和父类的该函数都重新写了一遍,有的新的内容
此时,子类的对象,无论是不是转换成了父类的类型,都会执行重写后的该函数
关于VS自动生成类重写函数
右键类名
点击快速修复或重构
点击生成重写
publicclassPerson{ publicstringname; publicPerson() { } publicPerson(stringname) { this.name=name; } publicvirtualvoidSay() { Console.WriteLine("我是父类的方法"); } } publicclassPerson1 : Person{ publicPerson1(stringname) { } publicoverridevoidSay() { Console.WriteLine("我是字类的方法"); } } staticvoidMain(string[] args) { Person1p1=newPerson1("我是字类"); p1.Say(); Personp=newPerson1("我是父类"); p.Say(); Console.ReadLine(); }
⌨⌨所有类的最终基类:Object
- 所以,所有类都可以重写Object类中的虚方法
- Object的虚方法有三个:
- Equals:描述对象与对象之间是否相等
- GetHashCode:将一个对象编程一串数字
- ToString:将一个对象转换为一个字符串
⌨⌨抽象方法
抽象方法的关键词abstruct
abstruct 返回值类型(参数列表)
抽象方法必须要放在抽象类里面
抽象方法没有方法体: [访问修饰符] abstruct 返回值类型 方法名(形参列表);
抽象方法的访问修饰符不能是private
抽象类即可以放抽象方法,也可以放普通方法
抽象方法必须在子类中全部实现
除非子类也是一个抽象类,那么可以先不实现该抽象方法
抽象方法和虚方法最大的区别
抽象方法必须其派生类中得以实现
而虚方法不是一定要在其派生类去重写
无论是虚方法还是抽象方法,子类进行了重写【实现】
那么子类的子类依旧可以继续重写
抽象类不能用sealed关键词修饰
总结:override可以重写哪些方法呢?
带有virtual、abstruct、override关键词的方法
代码:
//抽象类publicabstractclassPerson{ publicvoidFun(stringname) { Console.WriteLine(name); } publicabstractvoidSay(); } publicclassPerson1 : Person{ publicoverridevoidSay() { Console.WriteLine("asd"); } } staticvoidMain(string[] args) { Person1a=newPerson1(); a.Say(); Console.Read(); }
⌨⌨sealed关键词
sealed关键词修饰的类称之为密封类
语法:sealed class 类名
密封类是不能被别的类继承的
密封方法
sealed关键词修饰的重写的方法,称之为密封方法
语法:sealed override 返回值类型 方法名(参数列表)
密封方法无法再次被其子类重写
代码:
publicclassPerson{ publicvirtualvoidFun() { Console.WriteLine(1); } } publicclassPerson1 : Person{ publicsealedoverridevoidFun() { Console.WriteLine(2); } } publicclassPerson2 : Person1{ //这里报错 因为续承的Person1是密封函数publicoverridevoidFun() { base.Fun(); } } staticvoidMain(string[] args) { Persona=newPerson1(); a.Fun(); Console.Read(); }
⌨⌨静态类
关键词 static
静态成员
成员:字段、属性、方法
静态:跟对象没有任何关系,只跟类有关系
静态成员在何时开辟的内存
第一次访问这个类的时候【第一次用到这个类的时候】
比如:用这个类名去实例化一个对象
比如:用这个类型去访问一个静态字段
静态成员在何时释放内存
在程序结束的时候才会释放
普通的实例成员,每有一个对象,就有一个该成员
而静态成员,跟对象没有关系,所以无论有多少个对象,静态成员都只有一个
例: 实例成员【name】,每有一个人,就会有对应的一个名字
而静态成员【Population】,跟对象没有关系,无论有多少个实例对象,人口数量只有一个
静态方法中是不可以访问非静态的成员的
不能访问非静态的字段、属性
不能调用非静态的方法
非静态方法中是可以访问静态成员的
能访问静态的字段、属性
能调用静态的方法
静态方法是可以有重载
静态类
静态的成员可以放在静态类中,也可以放在非静态类中
静态类中只能存在静态成员,不能存在非静态的成员
静态类是不能进行实例化的
静态构造函数
只有一种写法
static 类名()
静态构造函数必须无参数
静态构造函数在什么时候才会调用
静态构造函数在程序运行期间只会执行一次
在第一次访问该类的时候调用
用这个类去new一个对象
用这个类去访问某个静态成员
用这个类去调用某个静态方法
如果有继承关系
静态构造函数的执行顺序是:
先执行子类的静态构造,再执行父类的静态构造
先子后父
静态构造有什么作用
一般用于对静态成员进行初始化
代码
classPerson{ publicstaticfloatage=88; publicstaticvoidFun() { Console.WriteLine("我是父静态类!"); } staticPerson() { Console.WriteLine("我是基静态类!"); } } classPer : Person{ staticPer() { Console.WriteLine("我是子静态类!"); } } staticvoidMain(string[] args) { Perp=newPer(); Console.WriteLine(); Console.ReadLine(); }
集合、栈、堆、队列、字典 ✍🔤🔤🔤
1、集合~范型(命名空间using System.Collections.Generic;)
1.1、ArrayList
代码:
//实例化动态数组ArrayListscore=newArrayList(); //向动态数组中添加元素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(newstring[] { "A", "B", "C", "A" }); //批量删除元素score.RemoveRange(2, 3); //如果数组中没有该下标所对应的元素,则也会出现越界异常Console.WriteLine(score[1]); //数组元素翻转score.Reverse(); //一般想要删除某个元素,会先进行判断是否存在boolcontainsA=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(newfloat[] { 1.1f,5.7f,4.5f,9.8f,3,2,1}); //从小到大排序score.Sort(); //清空动态数组//score.Clear();Console.WriteLine("-------------"); for (inti=0; i<score.Count; i++) { Console.WriteLine(score[i]); } Console.WriteLine("-------------"); foreach (variteminscore) { Console.WriteLine(item); }
1.2、List
代码:
//初始化范型集合List<int>list=newList<int>(); //添加元素list.Add(200); list.Add(250); list.Add(280); //批量添加元素list.AddRange(newint[] { 1,3,5,6,7,9 }); //移除某个元素list.Remove(280); //通过下标移除某个元素list.RemoveAt(0); list.RemoveAt(0); //批量删除list.RemoveRange(0, 3); intindex=list.IndexOf(9); Console.WriteLine(index); Console.WriteLine("-----------"); foreach (variteminlist) { Console.WriteLine(item); }
2、栈(Stack )
- 说明:后进先出
代码:
eg:非范型为例😥
Object<=Stackstack=newStack(); //进栈stack.Push("我是第一个进去的"); stack.Push("我是第二个进去的"); stack.Push("我是第三个进去的"); //出栈Console.WriteLine(stack.Pop()); Console.WriteLine(stack.Pop()); Console.WriteLine(stack.Pop()); Console.Read(); //返回栈顶的元素Peek();
常用方法
Stack.TryPeek(T) 方法
返回一个值,该值指示 Stack 的顶部是否有对象;如果有,则将其复制到 result 参数。 不从 Stack 中删除对象。
public bool TryPeek (out T result);
返回
Boolean
如果 Stack 的顶部有对象,则为 true;如果 Stack 为空,则为 false。
Stack.TryPop(T) 方法
public bool TryPop (out T result);
返回一个值,该值指示 Stack 的顶部是否有对象;如果有,则将其复制到 result 参数,并从 Stack 中删除它。
返回
Boolean
如果 Stack 的顶部有对象,则为 true;如果 Stack 为空,则为 false。
3、堆(heaps)
😀😀😀略略略
4、队列(Queue)
说明:先进先出
eg:进列
eg:出列
代码:
eg:非范型为例😥
Queuequeue=newQueue(); //进列queue.Enqueue("我是第一个进去的"); queue.Enqueue("我是第二个进去的"); queue.Enqueue("我是第三个进去的"); //出列Console.WriteLine(queue.Dequeue()); Console.WriteLine(queue.Dequeue()); Console.WriteLine(queue.Dequeue()); Console.Read();
常用方法:
5、字典(Dictionary)
代码:
Dictionary<string, int>dis=newDictionary<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 类名
类中的字段类型、方法参数、方法返回值,都可以使用类中的泛型
interface 接口名< T >
代码:
publicclassfanxing{ } publicstaticvoidFX<T>(Tsex, Tage) { Ttemp=sex; sex=age; age=temp; Console.WriteLine(age); } publicstaticvoidFX<T>(Tsex, Tage, Ta) { Ttemp=sex; sex=age; age=temp; Console.WriteLine(age); } staticvoidMain(string[] args) { FX<int>(7,8); FX<float>(7,8); Console.ReadLine(); } -范型方法的范型重载eg代码:```代码publicstaticvoidfaning<T>() { } publicstaticvoidfaning<T,F>() { } publicstaticvoidfaning<T,F,U>() { } staticvoidMain(string[] args) { faning<>}
🍺🍺🍺🍺委托与事件
1、委托(delegate)
1.1常见委托类型
- 什么是委托:相当于中介
- 委托的别名:代理、句柄
- 委托是自定义类型
- 委托是引用类型
代码eg:
eg:非范型为例😥
//定义委托delegatevoidweituo(floatmomey); classp1{ publicvoidzhao1(floatmomey) { Console.WriteLine("中介一需要:"+momey+"$"); } publicvoidzhao2(floatmomey) { Console.WriteLine("中介二需要:"+momey+"$"); } publicvoidzhao3(floatmomey) { Console.WriteLine("中介三需要:"+momey+"$"); } publicvoidzhao4(floatmomey) { Console.WriteLine("中介四需要:"+momey+"$"); } } internalclassProgram{ staticvoidMain(string[] args) { p1p=newp1(); weituowe; we=p.zhao1; we+=p.zhao2; we+=p.zhao3; we+=p.zhao4; we(1232143); Console.Read(); } }
1.2系统委托类型
- 无返回值系统委托 Action<>
代码eg:
eg:😥
classp1{ publicvoidwcs() { Console.WriteLine("我是无参数的中介需要:"+"18456456456456"+"$"); } publicvoidzhao1(floatmomey) { Console.WriteLine("中介一需要:"+momey+"$"); } publicvoidzhao2(floatmomey) { Console.WriteLine("中介二需要:"+momey+"$"); } publicvoidzhao3(floatmomey) { Console.WriteLine("中介三需要:"+momey+"$"); } publicvoidzhao4(floatmomey) { Console.WriteLine("中介四需要:"+momey+"$"); } } internalclassProgram{ staticvoidMain(string[] args) { p1p=newp1(); //使用系统委托//无参数Actionaction; action=p.wcs; action(); //参数Action<float>action1; action1=p.zhao1; action1+=p.zhao2; action1+=p.zhao3; action1+=p.zhao4; action1(182); Console.Read(); } }
2.有返回值系统委托 Func<>
代码eg:
eg:😥
classHout{ } classp1{ publicstringFunc1() { return"有返回值函数无参数:"; } publicHoutFunc2(stringname) { Console.WriteLine("有返回值函数有参数:"+name); returnnull; } } internalclassProgram{ staticvoidMain(string[] args) { p1p=newp1(); Func<string>func; func=p.Func1; Console.WriteLine(func()); Func<string,Hout>func1; func1=p.Func2; Houta=func1("先生"); Console.Read(); } }
1.3委托之匿名函数
代码eg:
eg:😥
classp1{ publicAction<string>action; publicstringname; publicintage; publicp1(stringname, intage) { this.name=name; this.age=age; } publicvoidisAction(stringage) { Console.WriteLine("我是个中介:"+age); if (action!=null) { action(age); Console.WriteLine("我是个中介:"+age); } } } internalclassProgram{ staticvoidMain(string[] args) { p1p=newp1("先生",18); p.action=delegate (stringa) { Console.WriteLine(a); Console.WriteLine("我好蒙啊2"); }; p.action+=read; p.isAction("我好蒙啊1"); Console.Read(); } publicstaticvoidread(stringname) { Console.WriteLine(name); Console.BackgroundColor=ConsoleColor.Red; Console.ForegroundColor=ConsoleColor.Black; } }
❌❌❌如何使用VS进行程序调试
程序是从Main函数开始,顺序执行的
调试就是在你觉得可能会发生问题的地方打下断点
什么是断点?
让程序执行到这个地方暂停下来的点
有什么好处,可以一句句或一段段让程序执行
调试步骤
给想要暂停的代码行添加断点
开始调试
通过监视或局部变量窗口,去看此时你想观察的变量的值
如果想看变量or对象的内存地址
找到即时窗口
&变量名