ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

C#学习第三周

C#学习第三周 #2026-9-27 抽象类abstract和多态一、抽象类abstract1. 什么是抽象类用abstract修饰的类叫抽象类它表示一个不完整的模板只定义应该有什么不实现或只实现一部分具体行为交给子类去完成。abstractclassAnimal{publicstringName{get;set;}// 抽象方法只有声明没有方法体publicabstractvoidShout();// 普通方法可以有实现子类直接继承使用publicvoidEat(){Console.WriteLine(Name 在吃东西);}}2. 抽象方法用abstract修饰只有声明没有方法体连{}都没有。抽象方法只能写在抽象类里。子类**必须重写override**所有抽象方法除非子类自己也是抽象类。classDog:Animal{publicoverridevoidShout(){Console.WriteLine(汪汪汪);}}3. 重要规则 抽象类不能被实例化Animal a new Animal();❌ 报错。但可以有构造函数供子类base()调用。抽象类里可以没有抽象方法但成员就不能是 abstract 的了。抽象成员不能是 privateprivate 子类看不到没法重写。抽象成员不能是 static也不能用 virtual 同时修饰。子类必须实现抽象成员否则编译不通过。抽象类可以被继承普通类 → 抽象类 → 具体类 都可以。4. 抽象类 vs 普通类 vs 接口对比项普通类抽象类接口能否实例化能不能不能能否有实现能能部分抽象默认不能方法体抽象方法无有都是抽象的继承数量单继承单继承可多实现二、多态Polymorphism1. 什么是多态同一个方法调用根据对象实际类型的不同表现出不同的行为。通俗说父类引用指向子类对象调用同一个方法结果不一样。Animala1newDog();Animala2newCat();a1.Shout();// 汪汪汪a2.Shout();// 喵喵喵同一个a1.Shout()写法结果不同 —— 这就是多态。2. 多态的实现方式三种① 虚方法 virtual override重写classAnimal{publicvirtualvoidShout(){Console.WriteLine(动物在叫);}}classDog:Animal{publicoverridevoidShout(){Console.WriteLine(汪汪汪);}}② 抽象方法 abstract overrideabstractclassAnimal{publicabstractvoidShout();}③ 接口实现interfaceIAnimal{voidShout();}classDog:IAnimal{publicvoidShout(){Console.WriteLine(汪汪汪);}}3. 补充小点 多态的前提继承 / 接口 方法重写 父类引用指向子类对象。编译看左边运行看右边编译时看父类有没有这个方法运行时执行的是子类重写后的方法。虚方法 vs 抽象方法virtual父类有实现子类可选择性重写。abstract父类没实现子类必须重写。重写 override vs 隐藏 newoverride真正多态运行时走子类方法。new隐藏父类方法不产生多态看引用类型走哪个。is和as多态场景下常配合类型判断和转换。if(a1isDogd){d.Shout();}Dogd2a2asDog;// 不匹配返回 null4. 多态的好处可扩展新增子类老代码不用改。解耦上层只依赖父类/接口不关心具体实现。统一调用一个数组/集合能装各种子类循环统一调用方法。Animal[]zoo{newDog(),newCat(),newDog()};foreach(Animalainzoo){a.Shout();// 各自发出不同叫声}三、小结主题核心要点抽象类abstract修饰不能实例化可含抽象方法和普通方法作为半成品模板抽象方法只声明无实现子类必须override只能存在于抽象类中多态父类引用指向子类对象同一调用因实际类型不同而行为不同实现方式virtualoverride、abstractoverride、接口实现记忆口诀抽象类只画框不填色子类来填必须填满。多态同一个口哨狗听了汪汪猫听了喵喵—— 一个调用多种表现。关键区别一句话抽象类是必须被继承的模板多态是同一接口、不同实现的运行时魔法。#2026-9-28 ArrayList集合队列栈一、ArraList集合本质是一个动态数组长度可自动增长不用像数组那样提前固定大小。可以存放任意类型的数据都当作object处理所以什么都能往里塞所以打印时也需要使用Convert强制转换。常见操作Add(值)添加元素Remove(值)/RemoveAt(索引)删除Insert(索引, 值)指定位置插入Count获取元素个数Clear()清空缺点因为存的是object装箱拆箱会损耗性能取出来用时还要强制转换类型容易出错。现在一般更推荐用ListT泛型集合替代它类型安全、效率高。二、Queue队列特点先进先出FIFO像排队买票先来的先走。常用操作Enqueue(值)入队加到队尾Dequeue()出队从队首取出并删除Peek()只看队首元素不删除Count元素个数适合场景任务排队、消息处理、按顺序逐个处理数据。三、Stack栈特点后进先出LIFO像一摞盘子最后放上去的最先拿走。常用操作Push(值)压栈放到栈顶Pop()弹栈从栈顶取出并删除Peek()只看栈顶元素不删除Count元素个数适合场景撤销操作CtrlZ、括号匹配、递归/回溯等。一句话对比集合存取规则典型操作ArrayList按索引随意存取Add / RemoveQueue 队列先进先出 FIFOEnqueue / DequeueStack 栈后进先出 LIFOPush / Pop#2026-9-29 异常泛型一、异常1. 什么是异常程序运行时出现的错误情况比如除零、数组越界、空引用、文件找不到。异常会中断正常流程需要捕获处理。2. try-catch-finally 结构try{inta10;intb0;intca/b;// 这里抛异常}catch(DivideByZeroExceptionex){Console.WriteLine(除零错误ex.Message);}catch(Exceptionex)// 兜底捕获所有异常{Console.WriteLine(出错了ex.Message);}finally{Console.WriteLine(无论如何都会执行);// 常用于释放资源}try放可能出错的代码。catch捕获并处理异常可以有多个从上往下匹配。finally不管是否出错都会执行用来收尾关闭文件、连接等。3. 补充小点 catch 顺序很重要具体异常要写在前面Exception兜底写最后否则后面的永远轮不到。不写 catch 只写 finally 也合法但不能只写 try 不写 catch/finally。异常一旦抛出try 中剩余代码不再执行直接跳到 catch。异常不是流程控制工具能预判的错误如除零前判断应优先用if处理别滥用 try-catch。性能开销抛异常比较贵频繁触发异常会拖慢程序。常见异常类型NullReferenceException空引用IndexOutOfRangeException索引越界FormatException类型转换格式错DivideByZeroException除零FileNotFoundException文件未找到4. 手动抛出thrownewException(自定义错误信息);throw用来主动抛出异常throw ex;会重置堆栈信息一般推荐throw;重新抛出保留原始堆栈。5. 自定义异常classMyException:Exception{publicMyException(stringmsg):base(msg){}}继承Exception即可方便区分业务错误。二、泛型1. 什么是泛型把类型当参数传递让同一套代码能处理不同类型做到类型安全 代码复用。2. 泛型类classBoxT{privateT_value;publicTValue{get{return_value;}set{_valuevalue;}}}Boxintb1newBoxint();b1.Value100;Boxstringb2newBoxstring();b2.Valuehello;T是类型参数用的时候再指定具体类型。3. 泛型方法publicstaticvoidPrintT(Titem){Console.WriteLine(item);}Printint(5);Printstring(abc);4. 泛型集合最常用ListintnumsnewListint();nums.Add(1);// 只能加 int编译期就检查Dictionarystring,intdicnewDictionarystring,int();dic[张三]90;对比上一课的非泛型ArrayList→ListTHashtable→DictionaryTKey, TValueQueue/Stack→QueueT/StackT5. 泛型约束where// T 必须是引用类型classATwhereT:class{}// T 必须是值类型classBTwhereT:struct{}// T 必须有无参构造函数classCTwhereT:new(){}补充约束让编译器知道 T “能干什么”才能调用其特定成员。6. 补充小点 泛型的最大好处避免装箱拆箱。Listint存 int 不会装箱ArrayList会。类型安全Listint里塞字符串在编译期就报错而不是运行时崩溃。性能更好泛型在运行时生成具体类型的代码省去强转和装箱。泛型不只用于集合泛型类、泛型方法、泛型接口、泛型委托都能用。命名约定类型参数通常用T多个用TKey、TValue等。泛型 vs 普通类型泛型类在编译后仍是通用的具体类型在运行时JIT才生成所以不受类型限制、又兼顾效率。三、小结主题核心要点异常try-catch-finally捕获处理throw抛出catch 顺序具体在前Exception 兜底泛型类型参数T类型安全 免装箱 代码复用ListT、DictionaryTKey,TValue是典型应用记忆口诀异常能预判就别用异常实在要用 try 包住兜底 catch 放最后finally 收尾跑不掉。泛型类型当参数一套代码吃遍所有类型安全又省心。
返回列表