NET中级工程师面试题(含详细答案·实战版)_第1页
NET中级工程师面试题(含详细答案·实战版)_第2页
NET中级工程师面试题(含详细答案·实战版)_第3页
NET中级工程师面试题(含详细答案·实战版)_第4页
NET中级工程师面试题(含详细答案·实战版)_第5页
已阅读5页,还剩4页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

.NET中级工程师面试题(含详细答案·实战版)说明:本套面试题贴合中小型企业、互联网公司真实中级.NET面试场景,覆盖日常开发高频考点,规避理论化空话,答案以实战落地、开发场景为核心,无书面化套话,适配3-5年.NET开发工程师岗位面试。一、C#核心语法与基础考点1、说说ref和out的区别,以及实际开发中的使用场景详细答案:两者都是为了实现方法内部修改实参数据,实现参数传址,核心区别在初始化和使用规范上:1)ref:传入的参数必须提前初始化赋值,方法内外都可以读取和修改参数值,双向传递数据。2)out:传入的参数无需提前赋值,但方法内部必须对参数赋值,否则编译报错,主要用于方法向外输出多个返回值。实战场景:ref常用于数值交换、结构体数据实时修改、高性能参数传递(避免值类型拷贝);out常用于框架自带方法,比如int.TryParse、Dictionary.TryGetValue,用于输出结果和状态,避免抛异常。2、value、readonly、const三者的区别详细答案:1)const:编译时常量,必须在声明时赋值,值不可修改,属于静态常量,全局共享,不能修饰局部变量、自定义对象,编译时会直接替换为固定值。2)readonly:运行时常量,可以在声明时赋值,或在类的构造函数中赋值,赋值后不可修改,属于实例常量,不同实例可以有不同只读值,可修饰静态、实例字段。3)value:不是修饰符,是属性set访问器中的隐式参数,代表外部赋值传入的数值,仅在属性set方法内有效。开发规范:固定不变的系统常量用const;需要构造初始化、实例独立的只读数据用readonly。3、string和StringBuilder的区别,为什么字符串拼接多了会卡顿详细答案:C#中string是不可变字符串,一旦初始化,内存中的值无法修改。每次对string进行拼接、截取、替换操作,都会在内存中新建一个字符串对象,旧对象会被丢弃,频繁操作会产生大量垃圾对象,触发GC回收,导致程序卡顿、内存占用升高。StringBuilder是可变字符串,底层维护字符数组,拼接、修改时不会新建对象,直接在原有内存空间扩容修改,性能极高。实战场景:少量固定拼接用string;循环拼接、批量文本处理、动态组装SQL/接口报文,必须用StringBuilder。4、装箱和拆箱是什么,有什么性能问题详细答案:装箱:值类型转换为引用类型(object、接口类型),会在堆中开辟新内存,拷贝值类型数据。拆箱:引用类型转回值类型,需要校验类型、读取堆内存数据,转换开销较高。性能问题:频繁装箱拆箱会产生大量堆内存垃圾,增加GC压力,循环中大量使用object接收值类型是常见性能坑。优化方案:使用泛型替代object传参,避免强制转换,从根源减少装箱拆箱。二、面向对象与设计思想1、面向对象三大特性,结合项目举例说明详细答案:1)封装:隐藏内部实现细节,只暴露公开访问接口。项目中比如实体类私有字段、公开属性,业务逻辑封装在Service内部,控制器只调用方法,不关心具体实现。2)继承:子类复用父类代码,减少冗余。项目中封装BaseService、BaseController,统一处理分页、异常、日志、权限校验,所有业务服务、控制器继承基类。3)多态:同一方法,不同子类有不同实现。项目中比如定义统一支付接口,微信支付、支付宝支付子类重写支付方法,调用时通过接口适配不同支付方式。2、接口和抽象类的区别,项目中如何选型详细答案:核心区别:1)抽象类:可以有字段、构造函数、已实现方法、抽象方法,单继承,侧重代码复用、模板定义。2)接口:不能有字段、构造函数,默认是抽象方法,支持多实现,侧重行为规范、功能约束。选型原则:需要统一模板、复用公共代码、控制子类结构,用抽象类;需要定义统一行为标准、多功能扩展、解耦业务,用接口。3、简述开闭原则、依赖倒置原则,日常开发怎么落地详细答案:1)开闭原则:对扩展开放,对修改关闭。新增业务功能时,尽量不修改原有成熟代码,通过新增类、新增接口实现扩展,避免改旧代码引发BUG。比如新增支付渠道,新增实现类,不改动原有支付核心逻辑。2)依赖倒置原则:高层模块不依赖低层模块,统一依赖抽象接口。开发中控制器依赖Service接口,不直接依赖具体实现类,后续替换实现方式、单元测试mock都更灵活。三、集合与泛型1、List和Array的区别详细答案:1)长度:Array长度固定,初始化后无法修改;List动态扩容,可随意增删数据。2)功能:Array仅有基础取值赋值功能;List封装了增删改查、排序、去重、筛选等大量实用方法,开发效率更高。3)性能:固定长度、高频读取场景,Array性能略优于List;频繁增删数据List更合适。4)底层:List底层本质是封装了Array,每次容量不足时会自动扩容(默认翻倍)。2、Dictionary和Hashtable的区别详细答案:1)类型安全:Hashtable是非泛型,存储object类型,存在大量装箱拆箱;Dictionary是泛型,类型安全,无装箱拆箱,性能更高。2)线程安全:两者单线程使用都安全;多线程读写场景下,都非线程安全,需要手动加锁。3)空值:Hashtable键不能为null,值可以为null;Dictionary同样键不可为null,泛型值类型不可为null,引用类型可以。开发建议:新项目一律用Dictionary,淘汰Hashtable。3、泛型的优势是什么详细答案:1)类型安全:编译时校验数据类型,避免运行时类型转换异常;2)性能提升:彻底避免装箱拆箱开销,值类型操作性能大幅优化;3)代码复用:一套泛型代码适配多种数据类型,无需重复编写重载方法;4)可读性强:无需频繁强制类型转换,代码更简洁清晰。四、多线程与异步编程1、Task和Thread的区别,项目中如何选用详细答案:1)Thread是操作系统级线程,粒度最细,开销大,资源占用高,无返回值,异常处理繁琐,适合简单后台常驻任务。2)Task是基于线程池封装的任务单元,粒度轻,复用线程池线程,减少资源创建销毁开销,支持返回值、取消、超时、异常捕获、链式调用,是.NET主推的异步方案。选型:日常异步开发、接口异步处理、耗时任务,全部用Task;极少场景需要手动控制线程生命周期才用Thread。2、async/await的工作原理,会不会阻塞线程详细答案:async是语法标识,标记方法为异步方法;await是暂停点,执行到await时,会释放当前线程,线程回归线程池处理其他请求,不会阻塞主线程/工作线程。等待的耗时任务(IO请求、数据库查询)执行完成后,会从线程池重新获取线程,继续执行后续代码。核心优势:IO密集型场景极大提升并发量,避免线程阻塞等待,充分利用服务器资源。误区:async/await不会加快单次请求速度,只会提升系统整体并发能力。3、多线程线程安全问题如何解决,常用锁的区别详细答案:多线程同时读写共享变量会出现数据错乱、脏数据,常用解决方案:1)lock锁:最常用,语法简单,锁定代码块,同一时间仅一个线程执行,性能适中,适合普通业务并发场景。2)Monitor:底层和lock一致,支持超时、手动释放锁,灵活性更高。3)Mutex:跨进程锁,可控制多个程序之间的资源竞争,开销大,一般不用在接口业务中。4)读写锁(ReaderWriterLockSlim):读多写少场景专用,允许多个读线程并发,写线程独占,性能远超普通lock。五、EF&数据库交互1、EFCore延迟加载和立即加载的区别,怎么配置使用详细答案:1)延迟加载(LazyLoading):查询主表数据时,不加载关联表数据,访问关联属性时才单独查询数据库。优点是节省单次查询开销,缺点是容易产生N+1查询问题。2)立即加载(EagerLoading):通过Include、ThenInclude主动指定关联表,一次性联表查询所有数据,仅执行一次SQL,避免多次查库,是业务开发首选。实战规范:业务查询一律使用Include立即加载,禁止依赖延迟加载,杜绝N+1性能问题。2、EF中AsNoTracking的作用和使用场景详细答案:EF默认会跟踪查询出来的实体对象,记录实体状态,用于后续修改、更新数据,跟踪机制会占用内存和性能。AsNoTracking关闭实体跟踪,查询性能更高、内存占用更小。使用场景:仅查询展示数据、报表统计、列表分页查询,不需要修改更新数据的场景,必须加AsNoTracking。新增、修改、删除业务不能使用。3、避免EF查询慢、数据库卡顿的常用优化手段详细答案:1)只查询需要的字段,禁止select*,用Select投影指定字段;2)分页查询必须先分页后筛选,避免查询全表数据;3)高频查询加AsNoTracking,关联查询用Include按需加载;4)关键查询字段建立数据库索引;5)复杂查询放弃EF,使用原生SQL、存储过程;6)高频静态数据、字典数据加入缓存,减少数据库查询次数。六、ASP.NETCore核心考点1、ASP.NETCore中间件的执行流程,自定义中间件怎么做详细答案:ASP.NETCore管道是请求进来逐层执行,响应返回逐层回溯的洋葱模型。请求从入口进入,依次经过注册的中间件(日志、跨域、路由、授权、异常处理),执行业务逻辑后,响应原路返回。自定义中间件两种方式:1)简单中间件:通过app.Use编写匿名委托,适合简单逻辑;2)自定义中间件类:实现InvokeAsync方法,封装独立逻辑,支持依赖注入,适合通用功能(全局日志、请求签名、限流)。2、依赖注入(DI)三种生命周期区别及使用场景详细答案:1)Singleton(单例):全局唯一实例,程序启动创建,程序关闭销毁,适合全局配置、工具类、缓存服务。禁止在单例中注入瞬时、作用域服务,会造成生命周期污染。2)Scoped(作用域):每次HTTP请求创建一个实例,请求结束销毁,是业务Service、仓储层的默认生命周期,最常用。3)Transient(瞬时):每次获取都创建新实例,轻量工具类、独立功能服务使用。3、接口跨域问题怎么解决,原理是什么详细答案:浏览器同源策略限制,前端域名、端口、协议与接口不一致时,会触发跨域拦截。ASP.NETCore中通过配置AddCors跨域服务,配置允许的域名、请求头、请求方式,管道启用UseCors中间件。原理:接口响应头携带Access-Control-*系列标识,告知浏览器当前请求允许跨域访问,浏览器放行请求。4、全局异常处理的实现方式,为什么不用try-catch写到处详细答案:项目中通过自定义全局异常中间件统一捕获所有接口异常,统一封装返回格式、记录错误日志、过滤系统异常和业务异常。不建议到处写try-catch的原因:代码冗余、异常处理规则不统一、容易遗漏异常、不利于日志统一统计排查,全局处理可以统一规范、精简业务代码。七、性能优化与实战故障排查1、项目接口响应慢,你的排查思路详细答案:1)先定位瓶颈:通过日志、监控判断是数据库慢、代码逻辑慢、IO阻塞、并发锁等待哪种问题;2)排查SQL:查看执行SQL是否全表扫描、未建索引、N+1查询、分页逻辑错误;3)排查代码:是否存在循环查库、频繁装箱拆箱、同步阻塞异步、死锁;4)排查缓存:高频数据是否未缓存、缓存失效频繁、缓存击穿;5)排查服务器:CPU、内存、线程池队列、网络带宽是否瓶颈。2、GC垃圾回收原理,如何减少GC压力详细答案:CLR会自动回收堆中无人引用的对象,分为0/1/2代回收,0代回收频率最高、速度最快,2代回收耗时最长,容易造成程序卡顿。减少GC压力的手段:1)减少临时对象创建,循环内不频繁new对象;2)杜绝频繁装箱拆箱;3)字符串拼接统一用StringBuilder;4)大对象复用,使用对象池;5)及时释放无用引用,避免内存泄漏。3、常见的内存泄漏场景及解决办法详细答案:1)静态集合无限添加数据,不清理:定时清空、限制容量;2)单例服务引用瞬时/作用域对象,导致对象无法释放:严格遵守DI生命周期规范;3)文件、数据库、网络流未手动释放:using语句包裹资源,自动释放;4)事件订阅未取消,宿主对象无法回收:使用弱引用,不用及时解绑事件。八、高频手写场景题1、简述using语句的作用和原理详细答案:using用于自动释放实现IDisposable接口的资源(数据库连接、文件流、网络请求等)。编译原理:using代码块会被编译为try-finally,无论代码正常执行还是抛出异常,finally中都会强制执行Dispose方法,释放资源,避免资源泄露。2、说说MVC和API的区别,以及MVC、MVVM思想详细答案:1)MVC:传统页面开发模式,Model数据、View视图、Controller控制器,控制器跳转页面、渲染视图,前后端不分离。2)WebAPI:纯接口模式,只返回JS

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论