.Net测试卷题一

1、什么是面向对象语言中的多态?给我一个例子。

  • 有多态之前必须要有继承,只有多个类同时继承了同一个类,才有多态这样的说法。在继承关系的前提下,实例化出不同的对象,这些对象调用相同的方法,但是却表现出不同的行为,这就叫做多态。
  • 在 C#语言中体现多态有三种方式:虚方法,抽象类, 接口。

2、抽象类和接口的区别有哪些,在使用的时候如何选择?

  • 相同点
    • 两者都是抽象类,都不能实例化。
    • interface实现类及abstrct class的子类都必须要实现已经声明的抽象方法
  • 不同点
    • 接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法;
    • 一个类一次可以实现若干个接口,但是只能扩展一个父类
    • 接口可以用于支持回调,而继承并不具备这个特点.
    • 抽象类不能被密封。
    • 抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,当然您也可以声明为虚的.
    • (接口)与非抽象类类似,抽象类也必须为在该类的基类列表中列出的接口的所有成员提供它自己的实现。但是,允许抽象类将接口方法映射到抽象方法上。
    • 抽象类实现了oop中的一个原则,把可变的与不可变的分离。抽象类和接口就是定义为不可变的,而把可变的座位子类去实现。
    • 好的接口定义应该是具有专一功能性的,而不是多功能的,否则造成接口污染。如果一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其他方法,就叫接口污染。
  • 使用
    • 如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单的方法来控制组件版本。
    • 如果创建的功能将在大范围的全异对象间使用,则使用接口。如果要设计小而简练的功能块,则使用接口。
    • 如果要设计大的功能单元,则使用抽象类.如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。
    • 抽象类主要用于关系密切的对象;而接口适合为不相关的类提供通用功能。
  • 以下是我在网上看到的几个形象比喻,真的非常不错:
    • 飞机会飞,鸟会飞,他们都继承了同一个接口“飞”;但是F22属于飞机抽象类,鸽子属于鸟抽象类。
    • 就像铁门木门都是门(抽象类),你想要个门我给不了(不能实例化),但我可以给你个具体的铁门或木门(多态);而且只能是门,你不能说它是窗(单继承);一个门可以有锁(接口)也可以有门铃(多实现)。门(抽象类)定义了你是什么,接口(锁)规定了你能做什么(一个接口最好只能做一件事,你不能要求锁也能发出声音吧(接口污染)。

3、Action<>和Func<>有什么区别

  • Action:表示不带返回值,可传递0到16个泛型参数的委托
  • Func:表示带泛型返回值,可传递0到16个泛型参数的委托

4、线程池中的线程在完成任务后的行为是什么

5、什么是泛型,以及它的好处?

  • 通过泛型可以定义类型安全类,而不会损害类型安全、性能或工作效率。您只须一次性地将服务器实现为一般服务器,同时可以用任何类型来声明和使用它。

6、C#中的对象被序列化时,它被转换成什么

  • json字符串

7、break 和 continue 关键字的区别

  • break:跳出循环
  • continue:跳出本次循环

8、什么是队列

  • “先进先出” 的原则
  • 队列存储结构的实现有以下两种方式:

9、简述你理解的 Linq

  • LINQ(发音:Link)是语言级集成查询(Language INtegrated Query)
  • LINQ是一种用来进行数据访问的编程模型,使得.NET语言可以直接支持数据查询
  • LINQ的目标是降低访问数据的复杂度
  • LINQ可以用统一的方法访问不同类型的数据,可以将数据作为对象使用
  • 能够更好地与编程模型集成

10、简述 C#的反射

  • 反射指的是提供封装程序集、模块和类型的对象(Type类型)。可以使用反射动态创建类型的实例,将类型绑定到现有的对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了特性,可以利用反射对它们进行访问。

11、简述 yield 关键字的作用

  • 是一个迭代器
  • 是语法糖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Program
{
static void Main(string[] args)
{
foreach (var item in GetNumsYield())
{
Console.WriteLine($" common return:{item}");
}
}

/// <summary>
/// 通过yield return 返回集合
/// </summary>
/// <returns></returns>
public static IEnumerable<int> GetNumsYield()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine($"yield return:{i}");
yield return i;
}
}
}

Untitled.png

12、C#能否直接操作内存,为什么

  • 不能,C#有垃圾回收机制,不能直接操作内存,但是可以调用基类的Finalize()方法。

13、简述控制反转 (IOC) 与依赖注入 (DI) 的关系

  • 依赖注入
    • 程序运行过程中,如果需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部的注入。通俗来讲,就是把有依赖关系的类放到容器中,然后在我们需要这些类时,容器自动解析出这些类的实例。依赖注入最大的好处时实现类的解耦,利于程序拓展、单元测试、自动化模拟测试等
  • 控制反转
    • 控制反转只是一个概念,也就是将创建对象实例的控制权(原本是程序员)从代码控制权剥离到 IOC 容器 中控制。
  • IOC/DI的优缺点:
    • 优点
      • 依赖注入把对象的创造交给外部去管理,很好的解决了代码紧耦合(tight couple)的问题,是一种让代码实现松耦合(loose couple)的机制
      • 松耦合让代码更具灵活性,能更好地应对需求变动,以及方便单元测试
    • 缺点
      • 目前主流的 IOC/DI 基本采用反射的方式来实现依赖注入,在一定程度会影响性能

14、有几种依赖注入方式

  • 构造函数注入
    • 目前构造方法注入是依赖注入推荐使用方式。
      • 优点
        • 在构造方法中体现出对其他类的依赖,一眼就能看出这个类需要依赖哪些类才能工作
        • 脱离了 IOC 框架,这个类仍然可以工作,POJO 的概念
        • 一旦对象初始化成功了,这个对象的状态肯定是正确的
      • 缺点
        • 构造函数会有很多参数(Bad smell)
        • 有些类是需要默认构造函数的,比如 MVC 框架的 Controller 类,一旦使用构造函数注入,就无法使用默认构造函数
        • 这个类里面的有些方法并不需要用到这些依赖(Bad smell)
    • public class FurionService{ private readonly IRepository _repository; public FurionService(IRepository repository) { _repository = repository; }}
  • 属性注入
    • 通过属性方式注入容易和类的实例属性混淆,不建议使用。
      • 优点
        • 在对象的整个生命周期内,可以随时动态的改变依赖
        • 非常灵活
      • 缺点
        • 对象在创建后,被设置依赖对象之前这段时间状态是不对的
        • 不直观,无法清晰地表示哪些属性是必须的
    • public class FurionService{ public IRepository Repository { get; set; }}
  • 方法参数注入
    • 方法参数注入的意思是在创建对象后,通过自动调用某个方法来注入依赖。
      • 优点:
        • 比较灵活
      • 缺点:
        • 新加入依赖时会破坏原有的方法签名,如果这个方法已经被其他很多模块用到就很麻烦
        • 与构造方法注入一样,会有很多参数
    • public class FurionService{ public Person GetById([FromServices]IRepository repository, int id) { return repository.Find(id); }}

15、ASPNET Core 项目中常见的工程文件和目录有那些?

目录文件说明
依赖项ASP.NET Core 开发、构建和运行过程中的依赖项,一般都是 NuGet 包和一些 SDK
Properties配置,存放了一些 .json 文件用于配置 ASP.NET Core 项目
Properties配置,存放了一些 .json 文件用于配置 ASP.NET Core 项目
Propertics/launchSettings.json启动配置文件,为一个 ASP.NET Core 应用保存特有的配置标准,用于应用的启动准备工作,包括环境变量,开发端口等
wwwroot网站根目录,存放类似于 CSS、JS 和图片、还有 HTML 文件等静态资源文件的目录
Program.cs这个文件包含了 ASP.NET Core 应用的 Main 方法,负责配置和启动应用程序
Startup.csStartup.cs 文件是 ASP.NET Core 的项目的入口启动文件

16、简述ASPNET Core中的依赖注入对象的生命周期

  • 瞬时(Transient)、作用域(Scoped)、单例(Singleton)

  • 「瞬时,就是没有生存期。」

    也就是说,每次从依赖注入系统中获取瞬时的服务实例时,都会创建一个全新的对象。

    依赖注入系统中的服务容器不会保存它,也就是没有生存权的普通对象。

  • 「单例,就是会一直存在,与应用同寿。」

也就是说,第一次从依赖注入系统中获取单例的服务实例时,才会创建一个全新的对象。

依赖注入系统中的服务容器会保存它,之后的每次使用都是直接从容器中获取它,也就是高贵的单例对象。

  • 「作用域,理解起来没有那么直观,需要结合场景来说明。」

比如,在 ASP.NET 的应用中,每一个来自外部的请求,都可以理解为是一个请求作用域。不同的请求,就是不同的请求作用域。

在同一个请求作用域中,获取作用域模式的服务实例与单例模式的服务实例,具有同样的表现。

也就是说,第一次从依赖注入系统中获取服务实例时,才会创建一个全新的对象。

依赖注入系统会在服务容器中为该作用域开个单间,单独保存该对象。

17、请列举常见的ASPNET Core 中间件

  • Log4Net、NLog(日志记录)
  • Unity、Ninject(IOC容器)
  • EF框架、NHibernate(ORM框架)
  • Quartz.NET(开源的作业调度框架)
  • Socket(通讯)、Redis(缓存)

18、ASPNET Core如何配置监听的IP 和端口

  • 参考第15题

19、什么是JWT SON Web Token),有什么优缺点

  • JWT的优点:
    • 可扩展性好 应用程序分布式部署的情况下,session需要做多机数据共享,通常可以存在数据库或者redis里面。而jwt不需要。
    • 无状态 jwt不在服务端存储任何状态。RESTful API的原则之一是无状态,发出请求时,总会返回带有参数的响应,不会产生附加影响。用户的认证状态引入这种附加影响,这破坏了这一原则。另外jwt的载荷中可以存储一些常用信息,用于交换信息,有效地使用 JWT,可以降低服务器查询数据库的次数。
  • JWT的缺点:
    • 安全性
      • 由于jwt的payload是使用base64编码的,并没有加密,因此jwt中不能存储敏感数据。而session的信息是存在服务端的,相对来说更安全。
    • 性能
      • jwt太长。由于是无状态使用JWT,所有的数据都被放到JWT里,如果还要进行一些数据交换,那载荷会更大,经过编码之后导致jwt非常长,cookie的限制大小一般是4k,cookie很可能放不下,所以jwt一般放在local storage里面。并且用户在系统中的每一次http请求都会把jwt携带在Header里面,http请求的Header可能比Body还要大。而sessionId只是很短的一个字符串,因此使用jwt的http请求比使用session的开销大得多。
    • 一次性
      • 无状态是jwt的特点,但也导致了这个问题,jwt是一次性的。想修改里面的内容,就必须签发一个新的jwt。

20、什么是 Refresh Token

  • Refresh Token 用于获取新的 AccessToken。这样可以缩短 AccessToken 的过期时间保证安全,同时又不会因为频繁过期重新要求用户登录。
  • 用户在初次认证时,Refresh Token 会和 AccessToken、IdToken 一起返回。你的应用必须安全地存储 Refresh Token,它的重要性和密码是一样的,因为 Refresh Token 能够一直让用户保持登录。

21、官方提供的GC模式有几种,ASPNET Core 默认是什么模式

  • .NET Core 两种GC模式: Server GC / Workstation GC
  • GC(garbage collection)是对内存管理中回收已经不用的内存的一种机制,java 和 .net 都有自己的 GC 机制,是内存管理的一部分。
  • Server GC : 主要应用于多处理器系统,并且作为ASP.NET Core宿主的默认配置。 它会为每个处理器都创建一个GC Heap,并且会并行执行回收操作。 该模式的GC可以最大化吞吐量和较好的收缩性。 …
  • Workstation GC : 主要应用于单处理器系统,Workstation GC尽可能地通过减少垃圾回收过程中程序的暂停次数来提高性能。
  • 默认模式
    • Server GC

22、简述Abp 的多租户实现逻辑

  • ABP vNext 实现多租户的思路也非常简单,通过一个 TenantId 来分割各个租户的数据,并且在查询的时候使用统一的全局过滤器(类似于软删除)来筛选数据。

23、简述Abp的权限认证实现逻辑

  • Abp 本身集成了一套权限验证体系,通过 ASP.NET Core 的过滤器与 Castle 的拦截器进行拦截请求,并进行权限验证。在 Abp 框架内部,权限分为两块,一个是功能(Feature),一个是权限项(Permission),在更多的时候两者仅仅是概念不同而已,大体处理流程还是一样的。

24、简述Abp的工作单元实现逻辑

  • 而在 Abp 的内部则是结合 Castle 的 Dynamic Proxy 拦截 UnitOfwork Attribute 来进行动态代理注入,实现了当执行标注了 [UnitOfwork] 方法时能够通过 UnitOfworkManager 来进行事务控制。