.Net Core常见面试题

忘忧 2022年11月03日 542次浏览

1. .Net Framework和.Net Core的区别

2. 什么是ASP.NET Core?

首先ASP.NET Core可以说是 ASP.NET的升级版本。它遵循了.NET的标准架构,是一个基于.NET Core的

Web开发框架, 可以运行于多个操作系统上。它更快,更容易配置,更加模块化,可扩展性更强。

3. Asp.Net Core框架优点

  • 依赖注入
  • 日志系统框架
  • 使用start up来注册服务 .Net6 已弃用
  • 更好的支持异步编程
  • signal IR,更好的支持WebSocket
  • 内置kestrel内核脱离IIS运行项目

4. 依赖注入

依赖注入是ASP.Net Core的核心,依赖注入我们可以分开来理解
依赖:当一个类需要另一个类协作来完成工作的时候就产生了依赖
注入:把依赖的创建丢给其它人,自己只负责使用,其它人丢给你依赖的这个过程理解为注入。

5. 依赖注入生命周期

  • Transient 每一次GetService都会创建一个新的实例 services.AddTransient<>()
  • Scoped 在同一个Scope内只初始化一个实例 ,可以理解为( 每一个request级别只创建一个实例,同一个http request会在一个 scope内) services.AddScoped<>()
  • Singleton 整个应用程序生命周期内只创建一个实例 services.Singleton<>()

6. IOC

IOC容器就是一个工厂,负责创建对象的
IOC控制反转:只是把上端对下端的依赖,换成第三方容器决定

7. 值类型和引用类型

基于值类型的变量直接包含值。将一个值类型变量赋给另一个值类型变量时,将复制包含的值。这与引用类型变量的赋值不同,引用类型变量的赋值只复制对对象的引用,而不复制对象本身。所有的值类型均隐式派生自 System.ValueType。与引用类型不同,从值类型不可能派生出新的类型。但与引用类型相同的是,结构也可以实现接口。与引用类型不同,值类型不可能包含 null值。然而,可空类型功能允许将 null 赋给值类型。每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。

值类型主要由两类组成:结构、枚举,结构分为以下几类:Numeric(数值)类型、int型(整型)、float型(浮点型)、decimal​bool​(布尔型)、用户定义的结构。引用类型的变量又称为对象,可存储对实际数据的引用。声明引用类型的关键字:classinterfacedelegate、内置引用类型:objectstring

8. 序列化与反序列化

序列化:将对象状态转换为可保持或传输的格式的过程。将对象实例的字段及类的名称转换成字节流,然后把字节流写入数据流

反序列化:将流转换为对象

9. 实现多态的过程中overload 重载与override 重写的区别

overload 重载是方法的名称相同,参数或参数类型不同,进行多次重载以适应不同的需要。

Override 是进行基类中函数的重写,实现多态。

10. 一列数的规则如下: 1、1、2、3、5、8、13、21、34… 求第30位数是多少,用递归算法实现

public class MainClass {
    public static void Main(){
        Console.WriteLine(Foo(30));      
    }
    public static int Foo(int i){
        if (i <= 0) return 0;
        else if(i > 0 && i <= 2) return 1;
        else return Foo(i - 1) + Foo(i - 2);
    }
}

11. 请编程实现一个冒泡排序算法?

int [] array = new int [*];
int temp = 0;
for(int i = 0; i<array.Length-1; i++){
    for(int j = i+1 ; j < array.Length ; j++){
        if (array[j] < array[i]){
            temp = array[i] ;
            array[i] = array[j] ;
            array[j] = temp ;
        }  
    }
}

12. AsNotracking的作用

EF Core 默认情况下对数据的访问都是启用模型跟踪

在第一次对象加载到内存中时进行一次快照,添加快照发生在返回一次查询或添加一个对象到DbSet中时。当Entity Framework需要知道对象的变动时,将先把当前实体与快照中的对象进行扫描对比。实现扫描对比的方法是调用DbContext.ChangeTracker的DetectChanges方法

变动跟踪代理:变动跟踪代理是一种会主动通知Entity Framework实体对象发生变动的机制。如:延迟加载的实现方式。要使用变动跟踪代理,需要在定义的类结构中,Entity Framework可以在运行时从POCO类中创建动态类型并重写POCO属性。动态代理就是一种动态类型,包含重写属性和通知Entity Framework实体对象变动的逻辑
  大部分的实例对象的变动调整需要在Entity Framework进行SaveChanges时才会知道,但也可以根据需要调用变动跟踪获取当前对象的状态。

Entity Framework Code FirstDbContext.DetectChanges在检测实例对象的变动时,大部分情况不会有性能的问题。但当有大量的实例对象在内存中,或DbContext有大量的操作时,自动的DetectChanges行为可能会一定程度的影响性能。

使用AsNoTracking方法查询返回无变动跟踪的Province的DbSet,由于是无变动跟踪,所以对返回的Province集中数据的任何修改,在SaveChanges()时,都不会提交到数据库中。

使用AsNoTracking()方法注意:

只能用于查询,不能把查询后的实体用作其他的用途,不然会导致其他的错误。例如:我想查询数据库有没有一条数据,用AsNotracking()查询后,如果有就把他赋值给一个实体,如果没有就new一个新实体 。这样的话,因为AsNotracking()没有把这个实体加到EF跟踪里面,EF就会认为这个实体在数据库不存在,就会把查询后的实体添加到数据库,但是实际情况是这个实体是存在于数据库里面的,这样就会报数据重复的错误。所以使用AsNotracking()只能用于查询,不能用于其他赋值的操作。

13. 在c#中using和new这两个关键字有什么意义,请写出你所知道的意义?using 指令和语句 new 创建实例 new 隐藏基类中方法。

using:引入名称空间或者使用非托管资源,使用完对象后自动执行实现了IDisposable接口的类的Dispose方法

new:新建实例或者隐藏父类方法

14. 什么是虚函数?什么是抽象函数?

虚函数:没有实现的,可由子类继承并重写的函数。​virtual CallSomeOne();​

抽象函数:规定其非虚子类必须实现的函数,必须被重写。​public abstract void CallSomeOne(); ​

15. 委托关键词

delegate 委托是一种定义方法签名的类型。当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联。您可以通过委托实例调用方法。

16. 事件关键词

event
事件在类中声明且生成,且通过使用同一个类或其他类中的委托与事件处理程序关联。包含事件的类用于发布事件。这被称为 发布器(publisher) 类。其他接受该事件的类被称为 订阅器(subscriber) 类。事件使用 发布-订阅(publisher-subscriber) 模型。

发布器(publisher) 是一个包含事件和委托定义的对象。事件和委托之间的联系也定义在这个对象中。发布器(publisher)类的对象调用这个事件,并通知其他的对象。

订阅器(subscriber) 是一个接受事件并提供事件处理程序的对象。在发布器(publisher)类中的委托调用订阅器(subscriber)类中的方法(事件处理程序)。

17. 不允许集成类

类声明时标记sealed

18. 常见名词

  • CLR Common Language Runtime 公共语言运行库

  • CTS Common Type System 通用类型系统

  • CLS Common Language Specification 通用语言规范

  • CIL Common Intermediate Language 公共中间语言

  • CLI Common Language Infrastructure 公共语言基础架构

  • BCL Base Class Library基础类库

  • FCL Framework Class Library 框架类库

  • JIT Just In Time .Net边运行边编译的一种机制

19. 什么是继承?什么是重载?

继承指子类可以拥有父类允许访问的属性、方法等。重载是一个函数通过参数类型或者数量区分不同的实现。

20. 什么是SQL注入,如何防止SQL注入攻击?

攻击者通过接口参数注入sql查询语句,代码没有过滤特殊字符时,在执行sql语句处填入’;等之类的字符来截断sql语句后再输入要执行的sql语句(删表等)来对数据库进行攻击。可以使用SQLParameter(把所有参数当字符串而不是关键字来处理)或者ORM来避免。

21. 简单存储过程示例

create proc delTable
@tname char(20) --入参
as
declare @cmd char(50)='truncate table '+@tname
exec(@cmd)

exec delTable '表名'

22. 常用的设计模式

  • 创建型
    1. 单例
    2. 原型
    3. 抽象工厂
    4. 工厂
    5. 建造者
  • 结构性
    1. 适配器
    2. 代理
    3. 策略
  • 行为型
    1. 责任链
    2. 观察者
    3. 模板方法

23. 装箱和拆箱

值类型到object是装箱,object到值类型是拆箱

24. Override 和重载的区别?

override是重写方法的关键字,重载指一个方法的不同实现

25. 面向对象的三大基本原则?

封装,继承,多态。

26. string str = null,string str = "",string.Empty 的区别?

null表示不存在于内存中没有地址,""表示存在于内存中的""这个对象,string.Empty 固定内存中存放的空字符串

27. 进程和线程的区别

进程是系统进行资源分配和调度的单位;线程是CPU分配和调度的单位。一个进程可以有多个线程,这些线程共享这个进程的资源。
(进程是系统层面,线程是CPU层面。线程∈进程)

28. 进程和线程分别该怎么理解?

进程是比线程大的程序运行单元,都是由 操作系统所体会的系统运行单元,一个程序中至少要有一个进程,有一个进程中,至少要有一个线程,线程的划分尺度要比进程要小,进程拥有独立的 内存单元,线程是共享内存,从而极大的提高了程序的运行效率同一个进程中的多个线程可以并发执行。

29. 当一个线程进入一个对象的方法后,其它线程是否可以进入该对象的方法?

不可以,一个对象的方法只能由一个线程访问。

30. 线程同步

  • 阻塞(调用Sleep()或Join())

  • 加互斥锁lock

  • 信号和句柄(AutoResetEvent/ManualResetEvent,调用Set()和WaitOne())

31. 描述Class和Struct异同?

Class属于引用类型,是分配在内存的堆上的;

Struct属于值类型,是分配在内存的栈上的;不能从另外一个结构或者类继承,本身也不能被继承;没有默认的构造函数,但是可以添加构造函数;可以不使用new 初始化

32. GC是什么?为什么需要GC?

GC(Garbage Collector)是垃圾收集器。.net中垃圾收集器会自动对内存垃圾进行回收管理,因为有了CLR的GC机制。正常情况下,.net会自动的帮忙释放内存,如果非托管代码,则需要手动释放,比如datareadWebRequest

33. try里有一个return语句,那么finally中的代码会不会执行,在return前还是return后?

会,在return前执行。

34. 堆和栈的区别?

栈上放的是由编译器自动分配释放的资源。堆上放的是代码中自己分配释放的资源,比如new对象时分配的内存空间

35. 什么是反射?

程序运行时动态获取程序集信息:接口、类、方法、属性等

36. 概述反射和序列化?

反射:要给发射下一个定义还是比较难的,这里先说说我的理解。反射提供了封装程序集,模块和类型对象,可以用反射动态地创建类型的实例,将类型绑定到现有对象,或者从现有对象类型里获取类型,然后调用类型的方法或访问字段和属性。
序列化:将对象转换为另一种媒介传输的格式过程。如,序列化一个对象,用Http通过internet在客户端和 服务器之间传递该对象,在另一端用反序列化从该流中重新得到对象

37. .NET中lock关键字根据什么来产生边界(线程同步)?

静态变量 (static object o=new Object();

38. 如何全局处理异常?

使用中间件(Middlware)记录处理异常,或者使用ExceptionFilter来捕获全局异常

39. 泛型的内部机制?

List<T>为例,第一次编译时只是为T生成一个占位符。在实际用到时比如List<User>时,JIT(Just-In-Time即时编译器)会用User去代替T的占位符实例化User,以此来实现泛型

40. a=“123”; b=“123”;内存怎么分布,b=a时呢?

"123"由于CLR的字符串驻留机制只存有一份。所以当a="123";b="123";时a和b都指向了"123"这个字符串的引用。
b=a时是把a的引用copy了一份给b

41. 什么是 Code First ,Data First, Model First

  • Code First 这种方式需要先写一些代码,如实体对象数据关系等,然后根据已有的代码描述,自动创建数据对象。
  • Data First 基于已存在的数据库,利用某些工具(如VS提供的EF设计器)创建实体类数据库对象实体类匹配关系等,你也可以手动修改这些自动生成的代码及匹配文件。也就是从一个数据库开始,然后生成实体框架和相应代码
  • Model First 利用某些工具(如VS的EF设计器)设计出可视化实体数据模型及他们之间的关系,然后再根据这些实体关系去生成数据库对象相关代码文件

42. 说说对EFCore中EntityState的理解

因为EFCore对于数据库的所有操作都是通过上下文DbContext来完成的,且是通过SaveChanges方法统

一落实到数据库中去的;EntityStateEFCore 在对数据库操作增删改的时候,记录当前被操作的数据对

象和Context的关系,针对与不同的操作,对应的一个状态信息,一共五种状态

  • Detached = 0, 当前对象和context没有任何关系,没有被上下文跟踪

  • Unchanged = 1, 当前对象被context跟踪,数据没有做任何修改

  • Deleted = 2, 当前对象被context跟踪,且标记是数据删除,调用SaveChanges后将会从数据中删

除;

  • Modified = 3, 当前对象被context跟踪,且有属性数据被修改过,调用SaveChanges后将会从数据中

修改;

  • Added = 4 , 当前对象被context跟踪,且数据并没有存在数据库中,调用SaveChanges后将会新增

到数据库中去;

43. 说说什么是EF Core中导航属性和引用属性

EF Core导航属性分为三种:

  • 集合导航属性:主表中对子表相关数据的引用
  • 引用导航属性:子表中对主表数据的引用
  • 反转导航属性:一个导航属性对应的另一端的导航属性

44. 请问对GRPC有了解吗,说说GRPC

有了解,说GRPC可以先说RPC,PRC:所谓RPC(Remote Procedure Call 远程过程调用)框架实际是提供了

一套机制,使得应用程序之间可以进行通信,而且也遵从server/client模型。使用的时候客户端调用

server端提供的接口就像是调用本地的函数一样。

所谓GRPC 是由谷歌开发的一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。目前提供

45. GRPC有几种模式?

四种模式:

  1. 简单模式:简单模式只是使用参数和返回值作为服务器与客户端传递数据的方式,最简单。

  2. 客户端流模式:即从客户端往服务器端发送数据使用的是,即服务器端的参数为流类型,然而在服

务器相应后返还数据给客户端,使用的也是流的send方法。一般在服务器端的代码,需要先recv再

send,而客户端与此相反。但是在后面的双向模式中可以使用go的协程协作。

  1. 服务器端流模式:即服务器端返回结果的时候使用的是流模式,即传入的数据是通过参数形式传入

的。但是在往客户端发送数据时使用send方法,与客户端返回数据的方式大同小异。

  1. 双向模式:客户端如果不适用协程,那么发送必须在接收之前。如果使用协程,发送与接收并没有先

后顺序。为了保证协程的同步,可以使用互斥量进行约束。

46. GPRC作为一种被调用的服务,有什么保护安全的措施吗?

可以使用授权验证(JWT.....),无论是对称可逆加密还是非对称可逆加密,都是可以支持的;

47. 什么是AOP

AOP(Aspect Oriented Programming)面向切面编程,它把系统需求按照功能分门归类,把它们封装在一个个切面中,然后再指定这些系统功能往业务功能中注入的规则。最后由第三方机构根据你指定的注入规则,将系统功能整合到业务功能中

48. .NET垃圾回收

.NET 的垃圾回收器管理应用程序的内存分配和释放。 每当有对象新建时,公共语言运行时都会从托管堆为对象分配内存。 只要托管堆中有地址空间,运行时就会继续为新对象分配空间。 不过,内存并不是无限的。 垃圾回收器最终必须执行垃圾回收来释放一些内存。 垃圾回收器的优化引擎会根据所执行的分配来确定执行回收的最佳时机。 执行回收时,垃圾回收器会在托管堆中检查应用程序不再使用的对象,然后执行必要的操作来回收其内存。

名词 解释
垃圾回收的基本知识 描述垃圾回收的工作原理、如何在托管堆上分配对象,以及其他核心概念
工作站和服务器垃圾回收 描述了客户端应用的工作站垃圾回收与服务器应用的服务器垃圾回收之间的区别
后台垃圾回收 描述了后台垃圾回收,它是在进行第二代回收时对第 0 代和第 1 代对象的回收
大型对象堆 描述了大型对象堆 (LOH) 及其垃圾回收方式
垃圾回收和性能 介绍了可用来诊断垃圾回收和性能问题的性能检查
已引发回收 描述如何完成垃圾回收
延迟模式 描述确定垃圾回收侵入性的模式
针对共享 Web 承载优化 介绍了如何在多个小网站共用的服务器上优化垃圾回收
垃圾回收通知 介绍了如何确定全面垃圾回收的开始时间和结束时间
应用程序域资源监视 介绍了如何监视应用程序域的 CPU 和内存使用情况
弱引用 描述允许应用程序访问对象的同时也允许垃圾回收器收集相应对象的功能

参考链接:描述垃圾回收的工作原理、如何在托管堆上分配对象,以及其他核心概念。

49. .NET中如何实现深拷贝(deep copy)?

实现ICloneable接口

50. .NET 中ICloneable的作用是?

详细阅读:https://docs.microsoft.com/zh-cn/dotnet/api/system.icloneable?view=net-6.0

支持克隆,即用与现有实例相同的值创建类的新实例。

ICloneable接口使您能够提供创建现有对象的副本的自定义实现。 ICloneable接口包含一个成员,即 Clone 方法,该方法旨在提供超出提供的克隆支持 Object.MemberwiseClone 。 有关克隆、深层副本和示例的详细信息,请参阅 Object.MemberwiseClone 方法

51. IOC&DI相关

IServiceCollection负责服务注册

IServiceProvider(一个内置的服务容器)负责提供实例。

52. 什么是ASP.NET Core中间件?

中间件指的是注入到应用中处理请求和响应的的组件,而这个过程我们称之为请求管道。

每个组件:

选择是否将请求传递到管道中的下一个组件。

可在管道中的下一个组件前后执行工作。

请求委托用于生成请求管道。 请求委托处理每个 HTTP 请求。

使用 Run、Map 和 Use 扩展方法来配置请求委托。 可将一个单独的请求委托并行指定为匿名方法(称为并行中间件),或在可重用的类中对其进行定义。 这些可重用的类和并行匿名方法即为中间件,也叫中间件组件。 请求管道中的每个中间件组件负责调用管道中的下一个组件,或使管道短路。 当中间件短路时,它被称为“终端中间件”,因为它阻止中间件进一步处理请求。

53. 中间件注册的三种方法?

Run(),使用Run调用中间件的时候,会直接返回一个响应,所以后续的中间件将不会被执行了。

Use(),它会对请求做一些工作或处理,例如添加一些请求的上下文数据,有时候甚至什么也不做,直接把请求交给下一个中间件。

Map(),它会把请求重新路由到其它的中间件路径上去。

54. 中间件执行顺序

参考资料
下图显示了 ASP.NET Core MVC 和 Razor Pages 应用的完整请求处理管道。 你可以在典型应用中了解现有中间件的顺序,以及在哪里添加自定义中间件。 你可以完全控制如何重新排列现有中间件,或根据场景需要注入新的自定义中间件。
middleware-pipeline

55. .NET Core中的五大过滤器及其用途

55.1. 授权过滤器(AuthorizeFilter

(1) 说明:它是过滤器管道中第一个过滤器,控制对方法的访问权限及授权策略

(2) 实现:继承Attribute类,实现IAuthorizationFilter接口,重写OnAuthorization方法。

注:继承Attribute类的目的是可以该过滤器以特性的形式作用于Controller或Action,下面过滤器都类似,不再说明。

(3).用途:通常用来做权限校验。

55.2. 资源过滤器(IResourceFilter

(1) 说明:只有授权过滤器在资源过滤器之前运行,里面的OnResourceExecuting重写是在创建控制器调用的。

(2) 实现:继承Attribute类,实现IResourceFilter接口,重写OnResourceExecuting 和 OnResourceExecuted方法。

(异步的话实现IAsyncResourceFilter接口,重写OnResourceExecutionAsync方法)

(3) 用途:做一些对变化要求不高的页面的缓存。

55.3. 操作、行为过滤器(ActionFilter

(1) 说明:分别在操作方法之前和之后执行

(2) 实现:继承Attribute类,实现IActionFilter接口,重写OnActionExecuting 和 OnActionExecuted方法。 或者直接继承ActionFilterAttribute类,观察源码可知,该类继承了Attribute类,而且还实现IActionFilter,IResultFilter接口。(异步的话实现IAsyncActionFilter接口,重写OnActionExecutionAsync方法)

55.4. 结果过滤器(ResultFilter

(1) 说明:在方法执行前后,且操作过滤器之后;结果(如:页面渲染)的前后运行。

(2) 实现:继承Attribute类,实现IResultFilter接口,重写OnResultExecuting 和 OnResultExecuted方法。 或者直接继承ResultFilterAttribute类,(或ActionFilterAttribute类), 观察源码可知,该类继承了Attribute类,而且还实现IResultFilter接口。(异步的话实现IAsyncActionFilter接口, 重写OnActionExecutionAsync方法) 还可以实现:IAlwaysRunResultFilter 或 IAsyncAlwaysRunResultFilter 接口。

(3).用途:可以获取action的返回结果,进行一些处理,比如:根据要求返回json数据或jsonp数据(详见cors章节)。

55.5. 异常过滤器(ExceptionFilter

(1) 说明:用于实现常见的错误处理策略,没有之前和之后事件,处理 Razor 页面或控制器创建、模型绑定、操作过滤器或操作方法中发生的未经处理的异常。 但无法捕获资源过滤器、结果过滤器或 MVC 结果执行中发生的异常 。

(2) 实现:继承Attribute类,实现IExceptionFilter接口,重写OnException方法。 或者直接继承ExceptionFilterAttribute类,观察源码可知,该类继承了Attribute类,而且还实现IExceptionFilter接口。(异步的话实现 IAsyncExceptionFilter接口,重写OnExceptionAsync方法)

(3) 用途:全局捕获异常,进行相关处理。

56. ASP.NET Core Filter的注册方式有哪些?

  • 方法注册:只对方法生效

  • 控制器注册:对控制器中的所有方法生效

  • 全局注册:对整个项目生效;

57. Startup类中两个方法的作用? .Net6 中已弃用类

ConfigureServices()方法配置应用程序所需的服务

Configure()方法配置应用程序的请求处理管道

58. Async,await 详解

C#异步编程入门看这篇就够了

PS 未完待续…

欢迎补充