学海无涯

导航

.NET Core 面试题

值类型和引用类型的区别?

值类型继承System.ValueType,例如:int、bool、double等,string为特殊的引用类型

赋值:值类型会产生一个新的数据副本,而引用类型是直接赋值引用。

内存分配:值类型分配在栈Stack上,而引用类型分配在heap堆上,值类型变量占用内存由系统分配和释放,而引用类型则由程序申请分配,释放由GC系统垃圾清理回收。

比较:值类型是直接比较内容,而引用类型是比较是否为同一个引用。

 什么是装箱和拆箱?

值类型转换成引用类型称为装箱。

引用类型转换成值类型称为拆箱。

C#中类型的修饰符和成员的修饰有那些?

Class:public、internal、private、protected、abstract、sealed、static

成员:public、private、protected、internal、static

C#有几种委托,区别是什么?

1. delegate(自定义委托)
        public delegate int TestDelegate(int x, int y);
2 .Action
       Action是无返回值的泛型委托。
Action 表示无参,无返回值的委托
Action<int,string> 表示有传入参数int,string无返回值的委托
3. Func
Func是有返回值的泛型委托
Func<int> 表示无参,返回值为int的委托
Func<object,string,int> 表示传入参数为object, string 返回值为int的委托
4. predicate
predicate 是返回bool型的泛型委托
predicate<int> 表示传入参数为int 返回bool的委托。
5 四者之间的区别
Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型
Action至少1个参数,至多4个参数,无返回值,
Func至少0个参数,至多4个参数,根据返回值泛型返回。必须有返回值,不可void
Predicate至少1个参数,至多1个参数,返回值固定为bool

面向对象的三大特征?

封闭、继承、多态

什么是IOC?

Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想

IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

什么是OOP?

面向对象程序设计(英语:Object-oriented programming,缩写OOP)是种具有对象概念的编程典范,同时也是一种程序开发的抽象方针。它可能包含数据特性代码方法。对象则指的是(class)的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性,对象里的程序可以访问及经常修改对象相关连的数据。

OOP的主要特征是:封装、继承和多态

什么是AOP?

AOP为 Aspect Oriented Programming 的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点。

总结一下:AOP能在不破坏封装的前提下,去额外扩展程序的功能。

  1. 聚焦业务,轻松扩展功能

  2. 代码复用,集中管理

OOP把系统看作多个对象的交互,AOP把系统分解为不同的关注点,或者称之为切面(Aspect)。

如何对调用方法进行拦截,并在拦截前后进行授权、日志、事务等处理,就相当于完成了所有业务功能。

.NET Core 实现AOP的几种方式?

  1. Filter方式:MVC流程部分,流程外处理不了

  2. 中间件方式:任何请求最外层到达,提前做些筛选过滤工作。但是中间件没有控制器

  3. 第三方容器(Autofac)::可以深入到业务逻辑层做AOP扩展

有那些过滤器 Filter ?

.net core自带五种过滤器,分别是验证、资源、动作、异常捕获、结果。

  1. Authorization Filter:身份验证

  2. Resource Filter:发生在控制器实例化之前

  3. Action Filter:发生Action在之前

  4. Exception Filter:捕获异常

  5. Result Filter:发生在视图替换环节

什么是DI?

DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。

.Net Core 中的经典设计模式

责任链模式

asp.net core 中间件的设计就是责任链模式的应用和变形,每个中间件根据需要处理请求,并且可以根据请求信息自己决定是否传递给下一个中间件。

建造者模式

asp.net core 中的各种 Builder, HostBuilder/ConfigurationBuilder 等,这些 Builder 大多既是 Builder 又是 Director,Builder 本身知道如何构建最终的 Product(Host/Configuration)

工厂模式

依赖注入框架中有着大量的工厂模式的代码,注册服务的时候我们可以通过一个工厂方法委托来获取服务实例,

依赖注入的本质就是将对象的创建交给 IOC 容器来处理,所以其实 IOC 容器本质就是一个工厂,从 IOC 中获取服务实例的过程就是工厂创建对象的过程,只是会根据服务的生命周期来决定是创建新对象还是返回已有对象。

单例模式

在 dotnet 中有一个 TimeQueue 的类型,纯正的饿汉模式的单例模式代码

class TimerQueue
{
    #region singleton pattern implementation

    // The one-and-only TimerQueue for the AppDomain.
    static TimerQueue s_queue = new TimerQueue();

    public static TimerQueue Instance
    {
        get { return s_queue; }
    }

    private TimerQueue()
    {
        // empty private constructor to ensure we remain a singleton.
    }

    #endregion

    // ...
}
策略模式

asp.net core 中的认证和授权,我觉得就是策略模式的应用,在使用 [Authorize] 的时候会使用默认的 policy,也可以指定要使用的策略 [Authorize("Policy1")] 这样就会使用另外一种策略 Policy1,policy 还是比较简单的

policy 是用来根据用户的认证信息来控制授权访问的,而认证则是根据当前上下文(请求上下文、线程上下文、环境上下文等)的信息进行认证从而获取用户信息的过程而不同的认证模式(Cookie/JWT/自定义Token等)其实是不同的处理方法,也就是策略模式中不同的算法实现,指定哪种认证模式,就是使用哪种算法实现来获取用户信息

观察者模式

常使用事件(event)进行解耦,外部代码通过订阅事件来解耦,实现对内部状态的观察

组合模式

WPF、WinForm 中都有控件的概念,这些控件的设计属于是组合模式的应用,所有的控件都会继承于某一个共同的基类, 使得单个对象和组合对象都可以看作是他们共同的基类对象

迭代器模式

c# 中定义了迭代器模式,原始定义:IEnumerable

适配器模式

使得 .net core 可以更方便的集成第三方的依赖注入框架,这里使用了适配器模式通过 ServiceFactoryAdapter 来适配各种不同的第三方的依赖注入框架

常见设计原则

SRP:单一职责原则

一个类应该只有一个发生变化的原因。

OCP:开放——封闭原则

软件实体(类、模块、方法等)应该是可以扩展的,但是不可修改。

LSP:里氐替换原则

子类型(subtype)必须能够替换掉它们的基类型(base type)

DIP:依赖倒置原则

a.高层模块不应该依赖于低层模块。二者都应该依赖于抽象。

b. 抽象不应该依赖于细节。细节应该依赖于抽象。

ISP:接口隔离原则

如果类的接口不是高内聚的,就表示该类具有胖接口。

客户程序应该仅仅依赖于它们实际调用的方法。

常用UML类图

状态图

对象图

有时,呈现出系统在某个特定时刻的状态是非常有用的。和一个正在运行系统的快照类似,UML对象图展示了在一个给定时刻获取到的对象、关系和属性值。

用例图

用例是从一个特定视角进行编写的关于行为需求的文本描述。

用例是对系统行为的描述。该描述是从一个让系统完成一些特定工作的用户视角编写的,用例记录了系统响应单个用户刺激所经历的可视事件序列。

顺序图

顺序图是UML用户最常绘制的动态模型。当你需要立即向某个人解释一组对象的协作方式或者当自己想要把这种协作关系可视化时,才使用顺序图。

类图

类图可以表示出类的静态内容以及它们之间的关系。在类图中,我们可以显示出类的成员变量和成员函数,以及类之间的继承和引用关系。简而言之,类图描绘出类之间所有源码级的依赖关系。

.NET Core 优点

支持跨平台:.Net Core 可以运行在 Windows、macOS、以及 Linux 操作系统上

采用模块化开发:程序用到什么模块,就安装什么模块,各个模块都可以单独升级,不同的程序可以选择适合自己版本的组件,不受系统上安装的其他程序的影响。

.Net Core 通过使用 NuGet 包管理

支持独立部署:可以把.NET Core 运行时环境和开发的程序打包到一起部署。这样就不需要在服务器上安装运行环境,这对容器化、无服务器等非常友好。

ASP.NET Core 程序内置了简单高效的 Web 服务器——Kestrel。Kestrel被嵌入在ASP.NET Core 程序中运行,因此整个程序其实就是一个控制台程序。

CLI工具:.Net Core 包含 CLI(Command-line interface)工具用于开发和持续集成。

浅克隆与深克隆(浅拷贝与深拷贝)

(1)浅克隆
在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。简单来说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制
通过实现ICloneable接口的Clone()方法,并调用MemberwiseClone()方法来实现浅克隆
(2)深克隆
在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制,如图:
在C#语言中,如果需要实现深克隆,可以通过序列化(Serialization)等方式来实现。序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来,可以实现深克隆。需要注意的是能够实现序列化的对象其类必须实现Serializable接口,否则无法实现序列化操作。

抽象类abstract class与接口interface的异同

相同点:
(1)都可以被继承
(2)都不能被实例化
(3)都可以包含方法的声明
不同点:
(1)抽象类被子类继承;接口被类实现
(2)抽象类只能被单个类继承;接口可继承接口,并可多继承接口
(3)抽象基类可以定义字段、属性、方法实现;接口只能定义属性、索引器、事件、和方法声明,不能包含字段
(4)抽象类可以做方法声明,也可做方法实现;接口只能做方法声明
(5)具体派生类必须覆盖(override)抽象基类的抽象方法;派生类必须实现接口的所有方法
(6)抽象类是一个不完整的类,需要进一步细化;接口是一个行为规范
(7)抽象类中的虚方法或抽象方法必须用public修饰;接口中的所有成员默认为public,不能有private修饰符

线程同步

(1)方法一:阻塞(调用Sleep()或Join())
(2)方法二:加互斥锁lock
(3)方法三:信号和句柄(AutoResetEvent/ManualResetEvent,调用Set()和WaitOne())

CLR(Common Language Runtime)

公共语言运行时,负责资源管理(包括内存分配、程序及加载、异常处理、线程同步、垃圾回收等),并保证应用和底层操作系统的分离。

GC(Garbage Collection)

当程序需要更多的堆空间时,GC需要进行垃圾清理工作,暂停所有线程,找出所有无被引用的对象,进行清理,并通知栈中的指针重新指向地址排序后的对象。
GC只能处理托管内存资源的释放,对于非托管资源则不能使用GC进行回收,必须由程序员手动回收,例如FileStream或SqlConnection需要调用Dispose进行资源的回收。

堆和栈

存放在栈中时要管存储顺序,保持着先进后出的原则,他是一片连续的内存域,有系统自动分配和维护;
堆是无序的,他是一片不连续的内存域,有用户自己来控制和释放,如果用户自己不释放的话,当内存达到一定的特定值时,通过垃圾回收器(GC)来回收。
栈内存无需我们管理,也不受GC管理。当栈顶元素使用完毕,立马释放。而堆则需要GC清理。
使用引用类型的时候,一般是对指针进行的操作而非引用类型对象本身。但是值类型则操作其本身。

什么是中间件?

中间件在这里是指注入到应用中处理请求和响应的组件。常见中间件有:Redis,Nginx,RabbitMQ,Kafka,链路跟踪

 

posted on 2023-01-27 09:49  宁静致远.  阅读(4491)  评论(1编辑  收藏  举报