一、基础知识
POP、OOP、AOP区别
POP:是面向过程,耦合度高
OOP:是面向对象,具有封装、继承、多态的特性;封装,隐藏细节,减少耦合,便于维护;继承,子类拥有父类的所有数据和操作;多态,重载与重写
AOP:面向切面:将多个模块的公共部分进一步提取成模块,提高程序的模块化;优点:提高可维护性,降低耦合度
AOP的实现
过滤器、缓存
CTS、CLS、CLR分别作何解释?
CTS:通用语言系统。CLS:通用语言规范。CLR:公共语言运行库。
什么是装箱和拆箱?
装箱:从值类型转换到引用类型。
拆箱:从引用类型转换到值类型。
简述 private、 protected、 public、 internal 修饰符
private : 私有成员, 在类的内部才可以访问。
protected : 保护成员,该类内部和继承类中可以访问。
public : 公共成员,完全公开,没有访问限制。
internal: 在同一命名空间内可以访问。
== 和equals区别
- 对于值类型,通常使用
==
来比较。 - 对于大多数引用类型,如果使用
==
来比较,比较的是两个对象的引用是否相同。如果需要判断两个对象的内容是否相等,应该使用Equals
方法。(需要重写Equals) - 对于string类型,使用
==
来比较,比较的是内容。(因为string
类型的==
操作符在.NET中被重载了)
字段与属性的区别
字段直接存储数据,一般被声明为私有的(private)来限制外部直接访问。
属性是对字段的封装,可以在get和set访问器中添加额外的逻辑,如验证输入值等。
特性与属性的区别
特性:以标签的形式为目标元素添加额外的信息。
属性:属性是对字段的封装。
C#中的委托是什么?事件是不是一种委托?
委托可以把一个方法作为参数代入另一个方法。
事件是一种特殊的委托
override与重载的区别
重写:子类对父类的方法进行重写。
重载:方法的名称相同,参数或参数类型不同。
什么情况用重写、重载
重写:在子类中改变父类某个方法时
重载:在一个类中为同一个方法名提供多个实现时
请叙述const与readonly的区别。
const:只能在声明时初始化。
readonly:可以在声明或构造函数中初始化。
请描述一下ref和out在方法参数传递上的异同点?
ref传入的参数必须先被初始化,out则不需要,out必须在方法中完成初始化。
out:用在需要多个返回值的地方
ref:需要在方法内部修改原始变量的值
什么是虚函数?什么是抽象函数?
虚函数:可由子类重写父类的函数。
抽象函数:非抽象子类必须重写的函数。
接口和类有什么异同?
接口是负责功能的定义,而类是负责功能的具体实现。
一个类只能继承一个父类,但可以继承多个接口。
抽象类和接口的区别和使用场景
主要区别
抽象类 | 接口 |
---|---|
可以有具体实现的方法和字段 | 只能有方法和属性,且方法不能有具体实现 |
不支持多继承 | 支持多继承 |
可以有构造函数 | 不能有构造函数 |
抽象类和接口的使用
- 抽象类表示共性,主要用于关系密切的对象。
- 接口则表示规范,适合为不相关的类提供通用功能。
- 如果要设计大的功能单元,则使用抽象类;如果要设计小而简练的功能块,则使用接口。
去重
使用HashSet:是一个不包含重复元素的集合
使用Distinct()
IEnumerable与IQueryable的差异
IEnumerable:在查询操作之前所有数据都会被加载到内存中,然后在内存中进行查询,消耗大量的内存资源
IQueryable:支持延迟执行,只有当数据真正被需要时,查询才会在数据库上执行
IEnumerable适用于内存中的数据集合,而IQueryable适用于可优化的远程数据源,如数据库
HashSet和集合List的区别
HashSet:是一个无序的集合,它不允许重复的元素。
List:是一个有序的集合,它允许重复的元素。
- 对于需要频繁查找、插入和删除操作,且不关心元素顺序的场景,
HashSet<T>
通常比List<T>
性能更好。 - 如果需要保持元素的插入顺序,使用
List<T>
。
数组Array和集合List的区别
数组 | 集合 |
---|---|
长度固定:一旦初始化了长度,不能自动增长。 | 大小是可变的,可以根据需要动态添加或删除元素。 |
在插入和删除操作上的效率较低 | 在插入和删除操作上相对灵活 |
字典Dictionary和集合List的区别
字典 | 集合 |
---|---|
通过键来访问值 | 通过索引来访问元素 |
查询速度快 | 内存使用少 |
使用场景
Dictionary<TKey, TValue>
: 当你需要根据键快速查找值时,或者当你需要存储具有唯一标识符的对象时,使用字典是合适的。List<T>
: 当你需要存储一系列同类型的元素,并且不需要快速基于键的查找,使用集合是合适的。
Hashtable和Dictionary区别
Hashtable | Dictionary |
---|---|
key和value都是object | key和value是泛型存储 |
Hashtable由于使用object,在存储或者读取值时都需要进行类型转换,所以比较耗时 | 是泛型存储,不需要进行类型转换 |
插入相同的键,替换原有的值 | 插入相同的键会抛出异常 |
堆和栈的区别?
堆是由程序员手动分配释放,栈是程序自动分配释放。
进程和线程的区别?
进程是系统资源分配和调度的单位
线程是CPU分配和调度的单位
一个进程可以有多个线程,这些线程共享这个进程的资源。
开启线程方式
new一个Thread().Start
Task.Run()
ThreadPool线程池
什么是线程安全和线程非安全
多个线程在并行执行且使用到了共享数据,最终得到了正确结果的就是线程安全的,如果结果不正确就是非线程安全
sleep() 和 wait() 有什么区别?
sleep()、wait()都能达到“暂停执行”的效果
sleep():是通过指定的时间间隔来“自我唤醒”的
wait():需要其他线程调用相应的唤醒方法 Pulse()
async await 会提高速度吗?
不会,可以提高应用程序的响应性和吞吐量(增加请求数量)
什么是异步/await,它们是如何工作的?
允许程序在等待耗时操作完成时,不阻塞执行线程,提高应用程序的响应性。
通过async标记异步方法,在异步方法内部使用await等待异步操作完成,在此期间,控制权会返回给调用者,以便执行其他任务,直到异步操作完成后再继续执行await之后的代码。
什么是 Nullable Type?
可空类型。通过使用 ? 运算符,在可空类型的实例上进行操作时,编译器会自动将其转换为 null 或具有值的对象。
什么是属性(Properties)?
属性提供了对字段的封装,可以在get和set访问器中添加额外的逻辑,如验证输入值等。
什么是委托(Delegates)?
它允许将方法作为参数传递给其他方法
具体来说,委托定义了一个方法签名,该签名包括返回类型和参数列表。任何与这个签名匹配的方法都可以通过委托来调用。
什么是泛型(Generics)?
将数据类型参数化,提高代码复用。
什么是反射(Reflection)?
在程序运行时动态获取类型信息,并且可以在运行时创建对象、访问和修改属性、调用方法等。
什么是 LINQ(Language-Integrated Query)?
类似 SQL 的查询语法,用于查询对象、集合等。
锁:悲观锁,乐观锁举例说明应用场景
悲观锁:每次去拿数据的时候都会上锁,这个时候如果别人也来拿这个数据,就会阻塞,一直等到我释放锁之后,别人才会去拿锁接着去执行!
乐观锁:每次去拿数据的时候,不会上锁,只有在更新的时候,会结合版本号这样的方式,判断当前有没有人在更新,如果有人更新,我就不会被修改,否则修改!提高了吞吐量!
悲观锁适用于冲突比较多的时候,而乐观锁适用于冲突比较少的情况!
什么是死锁?如何保证你实现的锁结果不发生死锁
多个进程或线程互相等待对方的资源,在得到新的资源之前不会释放自己的资源,这样就形成了循环等待,这种现象被称为死锁。
预防死锁
无法请求到新的资源就释放占有的资源,等一段时间后再次重新请求。
WebAPI 和 webservice的区别
webapi用的是http协议,webservice用的是soap协议。
webapi相对webservice更轻量级。
webapi支持多种数据格式,常用的json、xml;webservice主要使用XML作为数据传输格式
什么叫应用程序域?
可以理解为一种轻量级进程。起到安全的作用。占用资源小。
二、WebApi
描述一下依赖注入后的服务生命周期
Transient(瞬时):每次请求,都会创建一个新的实例。用的多
Scoped(作用域):在一个请求的生命周期内,只创建一个实例
Singleton(单例):在整个应用程序的生命周期内只创建一个实例
IOC容器中实现了IDispose接口的类,需要主动释放吗
正常来说不需要,除非出现了异常可能需要主动释放。
列举ASP.NET 页面之间传递值的几种方式
1.使用QueryString
2.使用Session变量
3.使用Server.Transfer
4.使用Application
5.使用Cache
6使用HttpContext的Item属性
7.使用文件
8.使用数据库
9.使用Cookie
MVC模式分层
Model(模型):负责处理数据和业务逻辑
View(视图):用户与程序交互的界面
Controller(控制器):负责协调Model和View
每个部分只关注于自己的职责,可以减少代码之间的耦合度,提高代码的清晰度和可维护性。
分离关注点、耦合性低、可维护性高、重用性高
MVC常用的ActionResult
ViewResult:返回一个视图结果
JsonResult:返回一个Json结果
FileResult:返回一个文件内容
ContentResult:返回简单的纯文本内容
EmptyResult:返回一个空的结果
RedirectResult:返回一个连接跳转
MVC和Web API之间的区别
MVC | Web API |
---|---|
用于构建 Web 应用。 | 用于构建 HTTP 服务 |
它返回一个视图 (HTML) | 它返回 REST 响应 |
HTTP GET 与 HTTP Post 的区别
Get | Post |
---|---|
其参数包含在 URL 中 | 其参数包含在正文中 |
不安全 | 安全 |
可缓存 | 不可缓存 |
ioc 与 di
Ioc(控制反转)是一种设计思想,将对象的创建和依赖关系的管理交给外部容器,而不是在代码内部手动处理。
DI(依赖注入)是一种具体的实现方式,使对象的依赖关系在创建时由外部传入,而不是在对象内部创建。
用于解耦,提高代码的灵活性和可维护性。
构造函数注入、属性注入。
Web API 中有哪些过滤器?AOP
Authorization Filters
(授权过滤器):该过滤器位于所有过滤器的顶端,首先被执行。授权过滤器用于确认请求用户是否已授权,如未授权,则可以将管道短路,禁止请求继续传递。Resource Filters
(资源过滤器):当授权通过后,可以在过滤器管道的其他阶段(如模型绑定)之前和之后执行自定义逻辑Action Filters
(操作过滤器):在调用Action之前和之后执行自定义逻辑。通过操作过滤器,可以修改要传入Action的参数,也可以设置或修改Action的返回结果。Exception Filters
(异常过滤器):当Action执行中抛出未处理的异常时,异常过滤器可以捕获并进行处理,可以设置返回结果。Result Filters
(结果过滤器):仅当Action的执行未抛出异常,或Action Filter处理了异常时,才会执行结果过滤器,允许你在操作结果执行之前和之后执行自定义逻辑。
在.NET Core Web API 中,常用的缓存
内存缓存(Memory Cache): 将数据缓存到进程的内存中,每次请求时直接从内存中读取数据,效率相对较高。
分布式缓存: 在多服务器项目中,可以采用分布式缓存来实现缓存的共享。
描述一下管道模式,以及在.net core 中的使用
将一系列的处理步骤串联起来,形成一个“管道”,数据通过这条“管道”流动,每经过一个步骤,数据就会被相应地处理,然后将处理的结果传递给下一个步骤继续处理。
内置的中间件
异常中间件、路由中间件、静态文件中间件、身份验证中间件等
ado.net五大对象
Connection :连接对象,用于执行与数据库的连接。
Command:命令对象,用于对数据库执行 SQL语句。
DataAdapter:适配器对象,用于填充数据集和更新数据库。
DataSet:数据集对象,内存中的数据库
DataReader:读取器对象,用于从数据库中快速逐行读取数据。
Parameter:参数对象,用于执行参数化 SQL语句。
Command和DataAdapter区别
Command侧重于执行SQL命令(如逐行读取);DataAdapter侧重于批量检索、更新。
DataSet 和 DataReader 的区别是什么?
DataSet:一次性读取数据到内存中,然后便与数据库断开连接。
DataReader:逐行读取,直到读完最后一行,才与数据库断开连接。在这期间,必须保持数据库的连接处于打开状态。
IdentityServer4
是一个认证框架,实现了OpenId Connect与OAuth2.0协议。
OAuth 2.0 主要关注授权流程,允许第三方应用代表用户获取对服务器资源的有限访问权限。
OpenID Connect 建立在OAuth 2.0之上,增加了身份认证层。在获得授权的同时,也能够验证用户的身份,并获取一个包含用户身份信息的ID令牌。
- Implicit:简化模式;直接通过浏览器的链接跳转申请令牌。
- Client Credentials:客户端凭证模式;适用于服务器到服务器的通信,客户端使用ID和密钥进行身份验证。
- Resource Owner Password Credentials:密码模式;适用于受信任的客户端,可以直接从用户那里获取用户名和密码。
- Authorization Code:授权码模式;适用于Web应用和SPA,提供较高的安全性。
Jwt是什么
是一种基于 Token 的认证授权机制
三、EF Core 8.0
如何优化EF的性能?
使用
AsNoTracking()
方法来取消跟踪查询结果使用
Select()
方法来只选择需要的字段,避免不必要的加载和查询使用
Find()
代替FirstOrDefault
:Find会优先查询缓存,而FirstOrDefault每次都会查询数据库
描述EF的几种开发模式
- CodeFirst 实体类生成数据库
- DbFirst 数据库生成实体类
- Model First 使用Visual Studio实体设计器,设计ER,同时生成Entity类DB
EF中映射实体对象的几种状态
Detached:该实体未由上下文跟踪。
Unchanged:实体将由上下文跟踪并存在于数据库中,其属性值与数据库中的值相同。
Added:实体将由上下文跟踪,但是在数据库中还不存在。
Deleted:实体将由上下文跟踪并存在于数据库中,但是已被标记为在下次调用 SaveChanges 时从数据库中删除。
Modified:实体将由上下文跟踪并存在于数据库中,已修改其中的一些或所有属性值。
EF延迟加载
可以根据需要动态地加载数据,从而减少了不必要的数据库查询
- 将导航属性标记为virtual,并在DbContext使用代理UseLazyLoadingProxies
四、DDD
ABP vNext
是一个模块化、基于DDD的应用框架,它提供了丰富的功能模块:租户、审计、用户等。
什么是领域驱动设计?
针对复杂需求的开发方法,目的是让系统中的领域模型和业务需求保持一致。
什么是领域模型?
是对业务领域的抽象描述,帮助开发人员更好的理解业务的核心概念以及它们之间的关系。
领域驱动的四个基本层
领域层:实现领域中的核心业务逻辑。
应用层:连接领域层和展示层,协调领域对象来执行任务。
展示层:包含应⽤程序UI元素。
基础层:集成工具库、第三方库来实现对其他层的⽀持。
规约
过滤领域对象
构件
实体、值对象、聚合和聚合根、仓储、领域服务、应用服务、DTO
什么是聚合?
⼀个聚合是⼀系列对象的集合,通过聚合根将所有关联对象绑定在⼀起。
什么是仓储
访问数据库,持久化数据,不写业务逻辑,专注数据处理
什么是领域服务
实现业务逻辑
什么是应用服务
调用领域服务执行业务逻辑,方法返回DTO
什么是DTO数据传输对象
用于在应用层和展示层之间传递数据
五、WPF
UI组件库使用:HandyControl
MVVM使用:Prism、Toolkit、MvvmLight
什么是WPF?
基于Windows的用户界面框架
相对于Winform,WPF有什么优势?
使用XAML实现界面设计更灵活、使用数据绑定实现数据自动更新、使用MVVM架构实现了用户界面与业务逻辑的分离
MVVM 的优势
实现了用户界面与业务逻辑的分离
命令设计模式是什么
处理用户界面操作的模式。将用户界面操作与执行操作的代码分离,提高代码可维护和可重用。
命令设计模式通过ICommand接口来实现。
ICommand是WPF中的一个接口,定义了三个方法:Execute、CanExecute和CanExecuteChanged。
页面假死
使用Dispatcher,把需要更新ui的代码放进去。协调UI线程和非UI线程操作
依赖属性
是一种特殊的属性,它的值不储存在自身,通过绑定获取。如Background
附加属性
将额外信息附加到不同元素上,而不破坏目标元素的层次结构。如Grid.Row
说说WPF中的XAML是什么?
基于XML的标记语言,用于定义WPF界面
XML和XAML有什么区别?
XML:用于存储和传输数据
XAML:定义WPF界面
WPF中的xmlns 和xmlns:x有什么区别?
xmlns用于引入和使用WPF的命名空间
xmlns:x用于引入和使用XAML的命名空间
什么时候应该使用“x:Name”和“Name”?
需要在 XAML 中引用元素时,应该使用 “x:Name” 属性
需要在代码中访问元素时,用哪个都行。
如何理解MVVM中的 View 和 ViewModel?
View(视图)用户界面,它负责展示数据和用户交互。
ViewModel(视图模型)用来连接View和Model,是它们之间的通信桥梁。
触发器
在满足指定的条件时更改控件的属性。常用的有Trigger,DataTrigger,EventTrigger。
资源字典
用于组织和管理程序资源的容器。如样式、控件模板
转换器
对数据进行转换处理,以满足UI展示的需求。
六、Redis
存储类型
String(字符串)、Hash(哈希,键值对集合)、List(列表)、Set(无序集合)、Zset(有序集合)
List与Set区别
List元素可以重复,Set不允许
List是有序的,Set是无序的
List与Zset区别
List中的元素可以重复,Zset不允许
List是一种有序的,Zset同样是有序的集合,Zset中的每个元素都会关联一个double类型的分数,基于这个分数排序
七、MySQL
MySQL事务得四大特性
- 原子性: 事务作为一个整体被执行,要么全部被执行,要么都不执行。
- 一致性: 指在事务开始之前和事务结束以后,数据不会被破坏。
- 隔离性: 多个事务并发访问时,事务之间是相互隔离的,即一个事务不影响其它事务运行效果。
- 持久性: 表示事务完成以后,该事务对数据库所作的操作更改,将持久地保存在数据库之中。
mysql 的内连接、左连接、右连接有什么区别?
- Inner join 内连接,在两张表进行连接查询时,只保留两张表中完全匹配的结果集
- left join 在两张表进行连接查询时,会返回左表所有的行,即使在右表中没有匹配的记录。
- right join 在两张表进行连接查询时,会返回右表所有的行,即使在左表中没有匹配的记录。
数据库的三大范式
- 第一范式:数据表中的每个字段都不可以再拆分。
- 第二范式:保证每个列直接依赖于主键
- 第三范式:非主键字段之间不能出现传递依赖的关系。
使表结构清晰,减少数据冗余,提高查询和存储效率
索引有哪几种类型?
- 主键索引: 数据列不允许重复,不允许为NULL,一个表只能有一个主键。
- 唯一索引: 数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。
- 普通索引: 基本的索引类型,没有唯一性的限制,允许为NULL值。
- 组合索引:多列值组成一个索引,用于组合搜索,效率大于索引合并
- 全文索引:是目前搜索引擎使用的一种关键技术,对文本的内容进行分词、搜索。
- 覆盖索引:查询列要被所建的索引覆盖,不必读取数据行
聚集索引和非聚集索引区别
聚集索引 | 非聚集索引 |
---|---|
一个表只能有一个聚集索引 | 一个表可以有多个非聚集索引 |
直接存储了数据行的实际数据 | 存储的是指向数据行的指针 |
查询效率较高 | 查询效率相对较低 |
索引有哪些优缺点?
优点
- 加快查询速度
缺点
- 创建索引和维护索引耗费时间
- 需要占物理空间
Where 和 Having 的区别?
where:在分组之前筛选出符合条件的数据
having:在分组之后筛选出符合条件的组
执行顺序:on->join->where->group by->having
drop、delete、truncate的区别
DROP:删除整个表的操作,包括表的结构和数据
DELETE:逐行删除表中的数据记录,通常配合where来使用,保留表结构
TRUNCATE:快速清空表中的所有数据,保留表结构,效率高。
优化Sql
限制行数,分页查询 limit
指定返回的记录数,offset
指定跳过的记录数
避免select *
八、Docker
Docker 是什么?
是一个开源的容器化平台,可以将应用及依赖打包到一个可移植的容器中。
Docker 与 虚拟机 有何不同?
特性 | Docker | 虚拟机 |
---|---|---|
启动速度 | 秒级 | 分钟级 |
交付/部署 | 开发、测试、生产环境一致 | 无成熟体系 |
性能 | 近似物理机 | 性能损耗大 |
体量 | 极小(MB) | 较大(GB) |
迁移/扩展 | 跨平台,可复制 | 较为复杂 |
Docker主要的三大核心组件
镜像(Image):是一个可执行的独立软件包,包含了程序运行所需的依赖项和配置。
容器(Container):基于镜像创建的运行实例,每个容器都是独立的。
仓库(Repository):是存放镜像的地方,类似于代码仓库。
描述Dockerfile和其用途
Dockerfile是一个文本文件,用于创建docker 镜像。【使用docker build命令创建】
Docker镜像和容器之间有什么区别?
镜像是静态的定义,类似于类;容器是镜像的实例,类似于对象。
容器有几种状态?
四种状态:运行、停止、重启、退出。
Docker常用基础命令包括
docker images:查看镜像
docker rmi:删除镜像
docker ps:查看当前运行的容器。加上-a参数可以看到所有容器,包括未运行的。
docker stop:停止容器
docker start:启动容器
docker run :运行容器
docker exec -it:进入容器
docker rm:删除容器
docker logs:查看Docker容器的日志
Dockerfile 中的命令 COPY 和 ADD 命令有什么区别?
容器与主机之间的拷贝
都有复制功能,只不过ADD还能自动解压文件,并支持从远程 URL 下载文件
什么是Docker卷(Volume)?
是一种数据持久化存储的机制,用来存储容器的数据。
如何创建和使用Docker卷?
使用docker run -v 挂载
使用docker volume create创建卷
什么是Docker Compose?
是一个工具,用于定义和运行多个容器
如何启动Docker Compose?
使用docker-compose up命令
简述什么是Docker Swarm?
Docker官方提供的容器集群管理工具