网站建设初步规划书,作文网课哪家好,网站安全建设方案需求分析,纯静态网站 维护刚入门C#后#xff0c;光会写单项目控制台程序可不够#xff0c;实际开发中不仅要会管理多项目、抽离公用代码#xff0c;还得吃透委托、Lambda、扩展方法、事件这些核心语法——它们不仅是日常开发的高频考点#xff0c;更是Linq、异步编程的基础#xff0c;也是面试中常…刚入门C#后光会写单项目控制台程序可不够实际开发中不仅要会管理多项目、抽离公用代码还得吃透委托、Lambda、扩展方法、事件这些核心语法——它们不仅是日常开发的高频考点更是Linq、异步编程的基础也是面试中常被问到的重点。今天这篇文章把C#进阶最核心的知识点一次性梳理清楚从多项目开发的实战技巧到索引器、密封类等基础进阶语法再到委托-Lambda-事件的完整体系每部分都配了可直接复制运行的代码示例新手也能一步步吃透建议收藏起来慢慢看、慢慢敲一、多项目开发实战必备的项目管理技巧实际开发中基本都是多项目协作而非单项目合理的项目结构能让代码更易维护、复用性更高。这部分重点讲项目创建、公用代码抽离、引用规则都是落地即用的技巧。1.1 项目创建的两种核心方式Visual Studio中创建C#项目核心有两种方式按需选择即可项目和解决方案一起建立新建项目时直接创建适合简单的多项目场景一步到位先建解决方案再添加项目先创建空解决方案再右键「添加→新建项目」适合复杂的多项目架构比如业务项目、类库项目、测试项目分离更灵活。1.2 公用代码抽离类库的创建与引用核心多个项目需要共用的类比如工具类、实体类不要重复写抽离到类库项目Class Library中其他项目通过「添加引用」复用这是解耦和提高复用性的关键步骤如下添加类库右键解决方案→添加→新建项目→选择「类库.NET Framework/.NET Core」写入公用类添加引用在需要使用公用类的项目上右键→添加→引用→勾选创建好的类库项目引用类方法在代码中通过using 类库命名空间;引入之后直接使用类库中的类和方法即可。1.3 多项目的配置文件读取规则重要规则多项目中只有主项目当前运行的项目的app.config/web.config配置文件读取才会生效其他项目的配置文件不会被加载。如果类库项目需要读取配置建议把配置项写在主项目的配置文件中。1.4 第三方类库的引用与反编译开发中用到第三方类库比如NuGet包、dll文件直接右键项目→添加→引用→勾选对应的dll即可如果需要查看第三方类库的具体代码可通过反编译工具比如ILSpy、dnSpy查看方便调试和理解用法。二、基础语法进阶索引器、密封类静态类这部分是C#的基础进阶语法看似简单实则是理解后续核心语法的铺垫重点记本质和使用规则。2.1 索引器无名称的“数组式属性”索引器可以让我们像操作数组一样操作自定义类的对象核心特点索引器没有名字本质是this[参数] {get; set;}不仅支持数字索引还支持字符串索引甚至允许多个索引器参数用法和属性类似分为get读取和set赋值适合需要按“索引”访问对象内部数据的场景。2.2 密封类静态类继承与实例化的限制两者都是对类的继承/实例化做了限制是面试高频考点对比记忆更清晰类型修饰符核心规则密封类sealed不能被继承防止类的方法被子类重写适合确定无需扩展的类静态类static1. 不能被继承2. 不能创建实例3. 内部成员必须是static类型4. 直接通过类名调用补充static成员不仅能在静态类中定义也能在非静态类中定义调用方式统一为类名.方法名/属性名无需创建类的实例。2.3 小补充string类的扩展方法string类是密封类不能被继承如果想给string扩展自定义方法通过扩展方法实现后文会详细讲比如给string加一个“判断是否为数字”的方法无需修改string原类。三、C#核心委托Delegate委托Delegate是C#的类型安全的函数指针简单说委托是用来封装方法的类型能把方法当作参数传递是Lambda、事件、异步编程的基础。核心记住日常开发基本不用自定义委托用.NET内置泛型委托就够了3.1 自定义委托基础语法先了解自定义委托的写法理解委托的本质语法如下// 定义委托delegate 返回值 委托名 参数列表delegate返回值 委托名(参数列表);// 实例化委托传入匹配的方法方法的返回值、参数列表需和委托一致委托名 委托实例new委托名(方法名);// 简化写法直接赋值方法名委托名 委托实例方法名;// 调用委托委托实例(参数);代码示例namespaceConsoleApp12{classProgram{staticvoidMain(string[]args){// 实例化委托两种写法都可MyDelmyDelnewMyDel(GetName);// MyDel myDel GetName;myDel(chen,1);// 调用委托输出chen1}// 匹配委托的方法staticstringGetName(stringname,intnum){returnnamenum;}}// 定义自定义委托delegatestringMyDel(stringname,intnum);}3.2 实战优选内置泛型委托Func Action.NET框架已经为我们封装了泛型委托Func和Action满足99%的开发场景无需自定义委托核心区别Action无返回值的委托支持0~16个参数比如Action、Actionstring、Actionint, stringFunc有返回值的委托支持0~16个参数最后一个参数固定为返回值类型比如Funcint、Funcstring, int、Funcint, string, bool。代码示例staticvoidMain(string[]args){Actiona1F1;// 无参数无返回值Actionstringa2F2;// 1个参数无返回值Funcstring,intf1F3;// 1个参数返回inta1();// 调用F1a2(测试);// 调用F2intresf1(chen);// 调用F3获取返回值}staticvoidF1()Console.WriteLine(F1);staticvoidF2(strings1)Console.WriteLine(F2s1);staticintF3(stringname)1;3.3 匿名方法无名称的临时方法如果某个方法只需要用一次没必要单独定义用匿名方法即可——本质是没有名字的方法直接赋值给委托语法委托实例 delegate(参数) { 方法体; }。// 示例匿名方法赋值给委托Actionintadelegate(ints){Console.WriteLine(s);};a(10);// 输出10注意匿名方法是Lambda表达式的“前身”实际开发中已经被更简洁的Lambda替代了解即可。四、值传递进阶ref 和 outref和out都是用来实现方法的按引用传递解决C#中值类型参数默认按值传递、方法内修改不影响外部的问题核心区别ref要求参数传入前必须初始化方法内可读写out要求参数方法内必须赋值传入前可未初始化方法内写完后外部才能用。两者都是实战中优化参数传递的小技巧比如方法需要返回多个值时可结合out使用。五、Lambda表达式简化委托的“语法糖”核心Lambda表达式是C#中最常用的语法糖本质是匿名方法的简化写法能极大减少代码量也是Linq的核心语法重点记简化规则配练习食用效果更佳5.1 Lambda的核心简化规则Lambda的核心符号是读作“goes to”结合委托使用从匿名方法到Lambda的简化步骤是由繁到简核心规则可省略参数的类型声明编译器会自动推断只有一个参数时可省略参数的圆括号()方法体只有一行代码时可省略大括号{}有返回值且方法体只有一行时可省略return关键字。5.2 5个经典练习吃透Lambda这5个练习由浅入深覆盖Lambda的所有使用场景代码可直接复制到控制台运行敲一遍就懂了练习1基础简化无返回值有返回值staticvoidMain(string[]args){// 无返回值一步步简化Actioninta1delegate(inti){Console.WriteLine(i);};Actioninta2(inti){Console.WriteLine(i);};Actioninta3i{Console.WriteLine(i);};// 单参数省略括号类型a1(3333);a2(4444);a3(5555);// 有返回值极致简化Funcint,string,boolf1delegate(inti,stringname){returntrue;};Funcint,string,boolf2(inti,stringname){returntrue;};Funcint,string,boolf3(i,name){returntrue;};// 省略类型Funcint,string,boolf4(i,name)true;// 一行代码省略return大括号f1(1,chen);f2(1,chen);f3(1,chen);f4(1,chen);Console.ReadKey();}练习2泛型结合Lambda实现通用找最大值自定义泛型方法通过Lambda传递比较规则让方法支持任意类型的数组找最大值适配int、string、自定义实体等staticvoidMain(string[]args){int[]numsnewint[]{3,88,6,9};// Lambda直接作为方法参数传递比较规则intmGetMax(nums,(i1,i2)i1i2);Console.WriteLine(m);// 输出88Console.ReadKey();}// 自定义比较方法可被Lambda替代staticboolcompareInt(inti1,inti2)i1i2;// 泛型找最大值方法staticTGetMaxT(T[]objs,FuncT,T,boolcompareFunc){Tmaxobjs[0];for(inti0;iobjs.Length;i){if(compareFunc(objs[i],max))maxobjs[i];}returnmax;}练习3自定义Where扩展方法Linq底层原理实现Linq中Where的核心逻辑通过扩展方法Lambda实现集合过滤理解Linq的底层本质// 静态类扩展方法的容器staticclassJiHeExt{// 扩展方法this关键字静态方法publicstaticIEnumerableTMyWhereT(thisIEnumerableTdata,FuncT,boolfunc){ListTresultListnewListT();foreach(Titemindata){if(func(item))resultList.Add(item);// Lambda作为过滤规则}returnresultList;}}classProgram{staticvoidMain(string[]args){int[]numsnewint[]{3,88,6,9};IEnumerableintr1nums.MyWhere(ii10);// 过滤大于10的数foreach(intiteminr1)Console.WriteLine(item);// 输出88Console.ReadKey();}}练习4Select方法集合数据转换Linq中Select的核心作用是数据处理/转换通过Lambda对集合中每个元素做处理生成新集合staticvoidMain(string[]args){Listintlist1newListint{1,2,3,8,16,99};// Lambda将int转换为string生成新集合IEnumerablestringdatalist1.Select(ii你好);foreach(varitemindata)Console.WriteLine(item);// 输出1你好、2你好、3你好、8你好、16你好、99你好Console.ReadLine();}练习5Linq高频方法Sum/ToList/ToArray结合Lambda操作自定义实体集合实战中高频使用比如求和、集合类型转换classProgram{staticvoidMain(string[]args){// 自定义实体数组Person[]pnewPerson[]{newPerson{Namechen,Age12},newPerson{Namechen2,Age24},newPerson{Namechen3,Age12}};inttotalAgep.Sum(ii.Age);// 求和12241248ListPersonpsListp.ToList();// 转List集合Person[]psArrayp.ToArray();// 转Array数组Console.WriteLine(totalAge);// 输出48Console.ReadKey();}}// 自定义实体类classPerson{publicstringName{get;set;}publicintAge{get;set;}}六、扩展方法不修改原类实现功能扩展扩展方法是C#的黑科技之一核心作用是在不修改原有类的代码、不继承原有类的前提下为类添加新的方法符合面向对象的开闭原则对扩展开放对修改关闭。扩展方法的三个必须条件缺一不可扩展方法必须定义在静态类中扩展方法本身必须是静态方法方法的第一个参数必须加this关键字且this后紧跟要扩展的类称为“扩展目标类”。核心应用Linq的所有方法Where、Select、Sum等都是通过扩展方法实现的也是我们日常开发中给第三方类、系统类如string、int扩展方法的核心方式。七、委托组合多个委托的“批量执行”C#支持委托的组合通过号将多个同类型的委托实例组合成一个委托链调用组合后的委托时会依次执行委托链中的所有方法也可通过-号从委托链中移除某个委托。代码示例classProgram{staticvoidMain(string[]args){Mydeld1F1;Mydeld2F2;Mydeld3F3;Mydeld4d1d2d3;// 委托组合形成委托链d4(8);// 依次执行F1、F2、F3输出对应内容Console.ReadKey();}staticvoidF1(inti)Console.WriteLine(我是F1i);staticvoidF2(inti)Console.WriteLine(我是F2i);staticvoidF3(inti)Console.WriteLine(我是F3i);}// 定义委托delegatevoidMydel(inti);八、事件委托的安全封装实战核心事件Event是委托的封装在委托的基础上加了event关键字让委托的使用更安全——这是WinForm、WPF、ASP.NET中事件驱动编程的核心比如按钮的点击事件Click。8.1 事件的基础实现实战示例以“本命年提醒”为例当Person的Age被赋值为12的倍数时触发“本命年”事件执行对应的方法// 定义实体类包含事件classPerson{privateintage;publicintAge{getthis.age;set{this.agevalue;// 当年龄是12的倍数时触发事件if(value%120)OnBenMingNian?.Invoke();// 空判断简化写法}}// 定义事件event 委托类型 事件名常用OnXXX命名publiceventActionOnBenMingNian;}// 主程序调用classProgram{staticvoidMain(string[]args){Personp1newPerson();p1.OnBenMingNianBMN;// 订阅事件 添加事件处理方法p1.Age5;// 不触发事件输出5Console.WriteLine(p1.Age);p1.Age24;// 触发事件输出“本命年到了”24Console.WriteLine(p1.Age);p1.Age55;// 不触发事件输出55Console.WriteLine(p1.Age);Console.ReadKey();}// 事件处理方法参数和返回值必须和事件的委托类型一致staticvoidBMN()Console.WriteLine(本命年到了);}8.2 事件vs委托核心区别很多小伙伴会混淆事件和委托核心区别就在于event关键字加了之后会有访问限制委托可在外部直接赋值、调用灵活性高但不安全事件在外部只能通过订阅、-取消订阅不能直接赋值、不能直接调用只能在定义事件的类内部触发更安全。本质反编译后会发现事件是由一个私有的委托变量add方法remove方法组成的对应调用add方法-对应调用remove方法。8.3 经典面试题接口中可以定义什么答案接口中可以定义方法、事件、属性、索引器。原因因为这四个元素的本质都是方法——属性是get/set方法索引器是this的get/set方法事件是add/remove方法所以接口中可以定义它们接口只能定义成员签名不能实现。九、文末总结敲代码建议今天的内容覆盖了C#从项目实战到核心语法的关键知识点核心重点总结为3点多项目开发核心是抽离类库、正确添加引用记住“只有主项目的配置文件生效”委托-Lambda-扩展方法三者是一套体系委托是基础Lambda是简化委托的语法糖扩展方法结合Lambda实现了Linq的核心功能事件是委托的安全封装核心是event关键字外部只能订阅/取消订阅是事件驱动编程的基础。最重要的建议一定要敲代码文中的所有代码示例都能直接复制到控制台运行先跑通再逐行修改、调试比如改Lambda的写法、改事件的触发条件只有动手才能把知识点从“看懂”变成“会用”。这些知识点是C#进阶的基础后续的Linq、异步编程async/await、设计模式比如观察者模式都离不开它们收藏起来反复看、反复敲一定能吃透最后想问大家你在C#开发中对委托、Lambda、事件的使用有哪些疑问或者遇到过哪些坑评论区聊聊关注我后续继续分享C#实战干货、面试考点从入门到进阶一起加油