• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
学习笔记
Misaka的学习笔记
博客园    首页    新随笔    联系   管理    订阅  订阅
.net面试题
  1. NET Core平台与.net framework相比有哪些优势?
    .NET Core和.NET Framework都是用于构建Windows和Web应用程序的跨平台框架。
    .NET Core是开源的,跨平台的,它可以在Windows,macOS,Linux等操作系统上运行。
    而.NET Framework只能运行在Windows系统上。
    优点:.NET Core具有更小的文件大小、更快的启动时间和更好的性能表现,同时还可以使用新的C#语言功能。
  2. 谈谈你对依赖注入的了解
    依赖注入(Dependency Injection,简称DI)是一种软件设计模式,旨在实现控制反转(Inversion of Control, IoC),
    从而促进代码的解耦和可维护性。在依赖注入中,一个对象的依赖关系由外部系统或容器管理,而非对象自身创建其依赖对象。
    这样做的目的是让对象专注于执行其核心职责,而将依赖管理的任务交给外部系统,例如依赖注入容器。 具体来说,依赖注入涉及以下几个关键概念: 依赖:当一个类A使用另一个类B的方法或属性时,A依赖于B。 注入:将一个对象传递到另一个对象的方法或构造函数中的过程,即注入。 依赖注入可以通过多种方式实现,包括但不限于: 构造器注入:在对象的构造函数中注入依赖。 方法注入:通过对象的方法参数传递依赖。 属性注入:通过对象的属性设置依赖。
  3. .NET CROE 内置依赖注入的三种生命周期:
    1、Transient(瞬时):即用即建,用后即弃。就是每次获取这个服务的实例时都要创建一个这个服务的实例。
    2、Scoped(作用域):这种类型的服务实例保存在当前依赖注入容器(IServiceProvider)上。在同作用域,服务每个请求只创建一次。
    3、Singleton(单例):服务请求时只创建实例化一次,其后相同请求都延用这个服务。
  4. 请简述.NET Core中的中间件(Middleware)的作用及其使用方法。
    中间件(Middleware)是.NET Core中的一种特殊组件,它可以处理HTTP请求和响应,并把请求传递到下一个中间件或终止请求。
    中间件在ASP.NET应用程序中扮演着非常重要的角色,能够为应用程序提供丰富的功能和服务,例如路由、认证、授权、缓存、日志、异常处理等。
    使用中间件在.NET Core应用程序中添加组件或服务非常简单
    ASP.NET Core加载中间件的顺序与它们添加到中间件管道的顺序相同,
    因此可以按照需要添加中间件并调整它们的顺序。
  5. 你在项目中使用过哪些ORM框架?EF Code和sqlsugar在项目中使用得多吗?
    SqlSugar是一款 老牌 .NET开源ORM框架
    1.  真正可以实现零SQL的ORM 建表、索引和CRUD全部支持
    2.  支持 .NET 百万级大数据写入、更新、分表和拥有几十亿查询统计成熟解决方案
    3.  支持 SAAS 完整应用 :跨库查询 、审计、租户分库 、租户分表 和 租户数据隔离
    4.  支持低代码+工作流  (动态建类 、动态建表、无实体多库兼容CRUD 、 JSON TO SQL 、自定义XML等)
    5.  支持ValueObject、鉴别器、仓储、UnitOfWork、DbContext、AOP 
    6.  支持 DbFirst、CodeFirst和WebFirst 3种模式开发
    7.  简单易用、功能齐全、高性能、轻量级、服务齐全、官网教程文档
  6. 反射(Reflection)在.NET中的使用场景?
    反射(Reflection)在.NET中提供了一种动态地获取和操作类型信息的能力。通过反射,我们可以在运行时获取类型的成员(属性、方法、字段等)信息,
    并进行动态创建对象、调用方法、访问和修改属性等操作。下面是一些常见的使用场景:
    1)插件和扩展性:通过反射,可以在运行时加载和实例化程序集中的类型,实现插件化和动态扩展的功能。
    这样,我们可以在不修改代码的情况下,动态地添加新的功能和模块。
    2)配置和元数据处理:通过反射,可以读取和处理程序集、类型和成员的元数据信息,如属性的注解、方法的参数信息等。
    这使得我们可以实现基于配置文件的动态配置和元数据驱动的开发。
    3)反射性能优化:通过反射,可以动态地生成和编译代码,从而提高代码的性能。
    例如,使用反射 Emit 或 Expression Tree 可以动态生成 IL 代码,实现高性能的动态代理、表达式解析和编译等。
    4)序列化和反序列化:反射可以在序列化和反序列化过程中使用,通过读取对象的成员信息,将对象转换为字节流或将字节流转换回对象。 5)调试和测试:在调试和测试过程中,反射可以帮助我们动态地获取对象的内部状态和调用私有方法,以便进行更详细的分析和测试。 6)动态代码生成和动态代理:通过反射,可以在运行时动态生成代码,并创建动态代理对象。这在某些情况下非常有用,如 AOP(面向切面编程)和远程代理等。
  7. 请解释.NET中的垃圾回收(GC)机制,以及它对内存管理的影响。
    在.NET中,垃圾回收(GC)是一种自动的内存管理机制,它负责管理.NET应用程序中的内存分配和释放。
    垃圾回收器在运行时自动识别和回收不再使用的内存对象,以便释放内存并减少内存泄漏的风险。
  8. 使用过ABP框架吗?知道DDD设计模式吗?并用你的理解讲讲它。
    ABP(http://ASP.NET Boilerplate)是一个流行的开源应用程序框架,用于构建跨平台的企业级应用程序。
    它基于http:
    //ASP.NET Core,并提供了一套丰富的开发工具和模块化组件,用于快速开发可扩展、可测试和可维护的应用程序。 DDD(Domain-Driven Design,领域驱动设计)是一种软件开发方法论,强调将业务领域的专业知识融入到软件设计和开发中 。DDD关注于解决复杂业务问题,并将业务逻辑和领域模型置于核心地位。 在ABP框架中,它借鉴了DDD设计模式的一些核心概念和原则,以帮助开发者构建符合领域驱动设计的应用程序。 以下是我对DDD设计模式的理解:
    1)领域:领域是指业务问题所涉及的特定领域,如电子商务、银行业务等。
    在DDD中,将业务领域抽象成领域模型。

    2)领域模型:领域模型是对业务领域的抽象和建模,它包含了业务实体、值对象、聚合根、领域服务等概念。
    领域模型通过对象和行为的组合来描述业务逻辑和规则。

    3)聚合根:聚合根是领域模型中的重要概念,它是一组相关对象的根实体,用于保证数据的一致性和完整性。
    聚合根通过封装一组对象和定义一些约束来管理领域模型中的业务逻辑。

    4)领域服务:领域服务是一些不属于任何特定实体的操作或行为,它处理领域模型中的复杂业务逻辑,提供一些跨实体的操作。

    5)值对象:值对象是不可变的对象,它表示一些具体的属性或属性集合。值对象没有唯一标识,主要用于封装和传递数据。

    6)聚合和聚合边界:聚合是一组相关对象的集合,它们共同构成一个单元,具有边界和一致性。
    聚合边界定义了聚合的边界范围,用于保证聚合内部的一致性和完整性。
  9. 你有过系统的性能调优的经验吗?列举你在项目中的调优的案例
    1.利用数据库事务批量提交
    使用更高效的数据结构和算法。
    使用缓存避免多次数据库交互
    减少不必要的计算和内存分配。
    利用并行和异步编程提高性能。
    使用性能分析工具定位和优化瓶颈。
    
     Web API方面:
    使用HTTP缓存减少不必要的请求。
    使用Gzip或Brotli压缩减少响应大小。
     使用分页、排序和过滤减少返回的数据量。
    
    数据库方面:
    使用索引加速查询。
    使用批量操作减少数据库交互次数。
    使用读写分离和数据库分片提高并发性能。
    
     Nginx方面:
    使用反向代理和负载均衡提高并发性能。
    使用缓存减少后端服务器的负载。
     使用Gzip压缩减少网络传输量。
  10. 请解释缓存(Cache)的作用和优势,以及你在项目中如何使用缓存进行性能优化?
    缓存(Cache)是一种临时存储数据的机制,将计算或获取的数据存储在高速访问的介质中,以便在后续访问中能够快速获取并提供响应。
    缓存的作用是提高系统的性能和响应速度,减轻对底层数据源的访问压力。在项目中使用缓存进行性能优化时,可以采取以下策略:

    1)查询结果缓存:对于频繁查询且结果不经常变动的数据,将查询结果缓存起来,下次需要同样的查询结果时直接从缓存中获取,减少数据库的访问。
    2)页面缓存:对于经常被访问的页面,将其渲染结果缓存起来,在后续请求中直接返回缓存的页面,减少服务器的计算和渲染时间。
    3)数据缓存:对于经常被读取的数据,如配置信息、静态数据等,将其缓存在内存中,减少对数据源的访问。
    4)查询缓存:对于复杂且耗时的查询,将查询语句和结果缓存起来,下次相同的查询可以直接返回缓存的结果,避免重复计算。
    5)分布式缓存:对于分布式系统,使用分布式缓存可以将数据存储在多个节点上,提高缓存的容量和可靠性。
    需要注意的是,缓存的使用需要考虑缓存数据的一致性和过期策略,避免缓存数据过期导致的数据不一致性问题。
    可以根据业务需求和数据特性来确定合适的缓存策略和缓存更新机制。
  11. 请列举你熟悉的前端框架和你在项目中使用它们的经验。
    Vue 的三种传值方式
    父传子:可以通过 V-bind 动态 绑定需要传的值
    
    子传父:通过 this.$emit("事件名A",传的值)
    
    兄弟之间传值:非父子组件之间传值,需要定义个公共的公共实例文件bus.js,作为中间仓库来传值,不然路由组件之间达不到传值的效果。
  12. 请讲讲Mvvm模式?
    MVVM(Model-View-ViewModel)是一种软件架构模式,用于在应用程序中实现数据、界面和业务逻辑的分离。
    MVVM模式由以下三个主要组件组成:
    Model(模型):模型代表应用程序的数据和业务逻辑。它包含了数据的获取、存储和处理的方法,以及与数据相关的业务规则。
    View(视图):视图是用户界面的可视部分。它负责展示数据和与用户进行交互。在MVVM模式中,视图是被动的,它只负责显示数据和转发用户输入到ViewModel。
    ViewModel(视图模型):视图模型是连接模型和视图的中间层。它包含了视图所需的数据和命令,并提供了与视图交互的方法。
    视图模型将模型中的数据适配为视图所需的形式,并将用户的操作转化为模型的操作。
  13. 讲讲你使用过的设计模式,并详解某个你熟悉的设计模式?
    单例模式:通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。
    工厂模式(Factory Method)是软件设计中的一种创建型模式,其本质在于将对象的创建过程与使用过程分离,
    通过定义一个接口或抽象类来让子类决定实例化哪一个类。
  14. 简述 Func与Action的区别?

    Func<T> 是一个委托类型,返回一个值。可以有0个或多个输入参数,并返回一个结果。
    例如:Func<int, int, int>表示一个有两个int输入参数并返回一个int结果的委托。 Action<T> 是一个委托类型,不返回值。可以有0个或多个输入参数。
    例如:Action<int, string>表示一个有两个输入参数(int和string)且不返回值的委托。
  15. C#中委托是什么?事件是不是委托?事件和委托的关系
    委托是一个类,将方法当作参数传入另一个方法的参数。委托的使用需要先声明,后实例化。接受一个将委托方法作为参数的构造函数。
    .net中有很多常见的委托如:Func 、Action 作用:提高方法的扩展性
    Func和Action委托的唯一区别在于Func要有返回值, Action没有返回值。
    事件是特殊的委托,用于消息机制。
    Action是无返回值的泛型委托,可以接受0个至16个传入参数 Action 表示无参,无返回值的委托
    Func是有返回值的泛型委托,
    可以接受0个至16个传入参数 Func 表示无参,返回值为int的委托 Func
    <object,string,int> 表示传入参数为object, string 返回值为int的委托
  16. 接口和类有什么区别?抽象和虚拟有什么区别
    接口定义功能,类实现功能。抽象函数只能在抽象类中声明;虚拟函数可以有实现。
  17. string和stringBuilder的区别
    string是不可变的引用类型;stringBuilder可变,适合频繁修改字符串。
  18. 请描述socket进行同步通讯编程的详细步骤
    服务端:创建Socket,绑定EndPoint,监听,接受连接,通信后关闭。
    
    客户端:创建Socket,连接EndPoint,发送和接收信息,通信后关闭。
  19. 介绍post和get的区别
    get提交显示在URL中,安全性低,数据量小;post提交隐藏在报文体中,安全性高,数据量大。
  20. 为什么C#使用反射比较慢?

    反射的核心在于它提供了一种动态类型信息访问机制。在运行时,反射允许程序查看和操控对象的元数据。
    这种动态行为虽然带来了极大的灵活性,但也意味着必须在运行时进行大量的类型检查和信息检索,这与编译时的静态类型检查相比,开销更大。 反射调用不能充分利用 .NET 的 JIT(Just
    -In-Time)优化机制。JIT 编译器在运行时会对代码进行优化,
    例如内联、循环展开等。然而,由于反射调用是动态的,JIT 编译器无法在编译时进行这些优化,从而导致反射调用的性能较低。 反射调用方法时,参数通常需要进行装箱和拆箱操作。装箱是将值类型转换为引用类型的过程,而拆箱则是将引用类型转换回值类型。
    这些操作不仅增加了额外的性能开销,还会导致垃圾回收频率的增加,进一步影响应用性能。 反射在调用方法时,会从方法数组中遍历查找匹配的方法。这种遍历查找过程会增加额外的时间开销,
    尤其是在类型包含大量方法的情况下,查找过程会更加耗时。 每次使用反射调用方法时,运行时都需要检查是否允许访问该方法。
    这涉及到安全权限的验证,确保调用者具有访问目标方法的权限。虽然这些检查是必要的以保证安全性,但也增加了额外的性能开销。
  21. C#中有哪些最常用的集合类型

    在.NET中,集合类型有很多种,如哈希表、队列、堆栈、字典和列表。
    不同的集合类型适用于不同的应用场景。
    
    集合是用来存储和管理一组相关数据的对象。
    它们提供了一种动态管理数据的方式,允许数据的添加、删除和访问。
    C# 中的集合类型基于一组通用的接口,这些接口定义了集合的基本操作,如添加、删除、枚举和查询等。
    
    ICollection 和 ICollection接口
    在 .NET 中,所有集合都直接或间接地基于 ICollection 或 ICollection<T> 接口。ICollection 接口定义了非泛型集合的大小、枚举和同步方法。
    
    IList 和 IList接口
    IList 和 IList&lt;T&gt; 接口继承自 ICollection 和 ICollection<T>,
    并添加了根据索引访问元素的方法。它们表示元素的有序集合,
    可以通过索引访问集合中的元素。
    
    IDictionary 和 IDictionary接口
    IDictionary 和 IDictionary<T> 接口继承自 ICollection 和 ICollection<T>,
    并添加了键值对集合的方法。
    它们表示具有键值对的集合,其中键是唯一的,值可以通过键进行访问。
  22. ASP.NET Core Web API上传多个文件和JSON数据的方法

    1、使用自定义包装类接收上传的文件及JSON数据
    
    2、使用ModelBinderAttribute标签实现
    
    3、用Postman测试
  23. .NET异步有多少种实现方式
    NET提供的执行异步操作的有三种模式
    基于任务的异步模式 (TAP)
    基于事件的异步模式(EAP)
    基于异步编程模型 (APM) 
    实现异步的方法有四种
    
    异步方法(Async Method TAP模式):使用async/await关键字实现异步编程
    
    任务并行库(TPL, Task Parallel Library TAP模式)通过 Task 和 Task类型实现异步编程,可以利用多核处理器,并发执行多个独立的任务。
    
    Asynchronous Programming Model(APM模式)是一种经典的异步编程模式,需要手动创建回调函数,用于处理完成或错误的通知。
    可以通过 IAsyncResult 设计模式的 Begin 和 End 方法来实现,其中 Begin 方法开始异步操作,而 End 方法在异步操作完成时执行,
    并返回异步操作的结果。 Event
    -based Asynchronous Pattern(EAP模式)是一种已过时的异步编程模式,需要使用事件来实现异步编程。
  24. 描述线程与进程的区别?

    线程(Thread)与进程(Process)二者都定义了某种边界,不同的是进程定义的是应用程序与应用程序之间的边界,
    不同的进程之间不能共享代码和数据空间,而线程定义的是代码执行堆栈和执行上下文的边界。
    一个进程可以包括若干个线程,同时创建多个线程来完成某项任务,便是多线程。
    而同一进程中的不同线程共享代码和数据空间。用一个比喻来说,如果一个家庭代表一个进程,在家庭内部,各个成员就是线程,
    家庭中的每个成员都有义务对家庭的财富进行积累,同时也有权利对家庭财富进行消费,
    当面对一个任务的时候,家庭也可以派出几个成员来协同完成,而家庭之外的人则没有办法直接消费不属于自己家庭的财产。
  25. using关键字有什么用?跟IDisposable有啥关系?

    using可以声明namespace的引入,还可以实现非托管资源的释放,实现了IDisposiable的类在using中创建,
    using结束后会自动调用该对象的Dispose方法,释放资源。
    加分的补充回答:using其实等价于try……finally,用起来更方便。
  26. 前台线程和后台线程有什么区别?

    通过将 Thread.IsBackground 属性设置为 true,就可以将线程指定为后台线程
    
    托管线程可以是后台线程,也可以是前台线程。
    后台线程和前台线程几乎完全相同,只有一处不同,即后台线程不会确保托管执行环境一直运行。
    一旦托管进程(其中 .exe 文件为托管程序集)中的所有前台线程都停止,系统会停止并关闭所有后台线程。
    
    前台线程:应用必须结束掉所有的前台线程才能结束程序,
    只要有一个前台线程没退出进程就不会自动退出,
    当然线程是依附在进程上的,
    所以你直接把进程KO掉了的话自然所有前台线程也会退出。
    
    后台线程:进程可以不考虑后台直接自动退出,
    进程自动退出后所有的后台线程也会自动销毁。
  27. await的作用和原理,并说明和GetResult()有什么区别?

    async 关键字
    •定义异步方法:在方法前加上 async 关键字,表示该方法是异步的,可以包含 await 表达式。
    返回类型:async 方法通常返回一个任务(Task 或 Task),表示异步操作的结果。对于不返回值的异步方法,返回类型是 Task;
    对于返回值的异步方法,返回类型是 Task<T>。 await 关键字 •等待异步操作:await 关键字用于等待一个异步操作完成。它会暂停方法的执行,直到异步操作完成,然后继续执行方法的剩余部分。 •释放线程:在等待异步操作完成时,await 会释放当前线程,使其可以执行其他任务,从而提高应用程序的并发性能。
  28. 说说常用的锁,lock是一种什么样的锁?

    常用的如如SemaphoreSlim、ManualResetEventSlim、Monitor、ReadWriteLockSlim,lock是一个混合锁,其实质是Monitor
  29. lock为什么要锁定一个参数(可否为值类型?)参数有什么要求?

    lock的锁对象要求为一个引用类型。她可以锁定值类型,但值类型会被装箱,每次装箱后的对象都不一样,会导致锁定无效。
    
    对于lock锁,锁定的这个对象参数才是关键,这个参数的同步索引块指针会指向一个真正的锁(同步块),这个锁(同步块)会被复用。
  30. 描述使用linq实现两个对象集合左连接?
    在使用LINQ(Language Integrated Query)实现两个对象集合的左连接时,可以使用join关键字和into子句来实现。
posted on 2025-06-26 15:16  我们打工人  阅读(59)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3