某外企.NET全栈技术一面全真面试题

莫小星 · 发布于 2026-09-05 17:15 · 面试真题 · 6 次阅读
某外企.NET全栈技术一面全真面试题

这是小编收集整理某老外面试.NET全栈开发一面面试题。废话不多说,还是先列出面试问题,你可以先试答一下;答案在文末同意给出,

第一部分:C# 语法与面向对象基础(OOP)

  1. 显式接口实现:如果一个类同时实现两个接口,且这两个接口包含同名同签名的方法,在类中如何分别调用和实现这两个接口的方法?
  2. 参数修饰符:请详细阐述 C# 中 outref 参数修饰符的核心区别。在方法调用时,两者对变量初始化的要求有何不同?
  3. 字符串处理StringStringBuilder 在内存模型和可变性上的本质区别是什么?请结合性能考虑,说明在拼接大量字符串时为何首选 StringBuilder
  4. 静态构造函数:静态构造函数有何特征?它何时被 CLR 调用?它与实例构造函数在执行顺序和访问修饰符上有何不同?
  5. 委托机制:什么是委托(Delegate)?它本质上是基于什么类型?简述委托的多播(Multicast)特性及其用途。
  6. 终结器与资源管理Finalize 方法(终结器)在 C# 中是什么?它与 Dispose 模式在资源释放时机和确定性上有什么根本性差异?
  7. 对象实例化过程:在 .NET 托管堆上,使用 new 关键字创建一个对象时,CLR 在后台大致经历了哪几个核心步骤(涉及内存分配、类型指针同步、构造函数调用等)?
  8. 方法重写与多态:(注:原题缺失具体代码,此处修正为通用考察点)在继承体系中,如果基类方法标记为 virtual,子类使用 override 重写。请说明当基类引用指向子类对象时,调用该方法的运行时分派机制,并给出代码示例阐述 base 关键字在重写中的用法。
  9. 引用类型赋值行为:当创建一个引用类型对象并将其赋值给另一个变量后,再对其中一个变量重新实例化(new)或置为 null,另一个变量的值或状态会受到怎样的影响?请说明引用传递和值传递在此场景下的区别。

第二部分:ASP.NET Core 与依赖注入(DI)

  1. 依赖注入:什么是依赖注入(DI)?请简述构造函数注入(Constructor Injection)和属性注入(Property Injection)的优缺点。
  2. 中间件管道:什么是 ASP.NET Core 中的中间件(Middleware)?请描述请求处理管道的执行顺序(即 UseRun 的委托链),以及 next() 委托的作用。
  3. 身份认证与授权:解释 Authentication(认证)与 Authorization(授权)的区别。在 .NET Core 中,你通常如何实现基于策略(Policy)的授权?
  4. Web API 安全:针对 Web API,你会采取哪些核心安全措施?请至少从认证方案(如 JWT)、输入验证、CORS 跨域配置、HTTPS 强制和防 CSRF 攻击五个维度简述。
  5. 服务生命周期:分别阐述 Transient、Scoped 和 Singleton 的生命周期特征。在 ASP.NET Core 中,AddDbContext 默认注册的是哪种生命周期?为什么?
  6. Web 服务对比:简要对比 SOAP 与 RESTful 架构风格的核心差异(包括协议、消息格式、状态管理方面)。

第三部分:SQL Server 与数据库编程

  1. SQL 删除命令:DELETE、TRUNCATE 和 DROP 三者有何本质区别?请从操作类型(DML/DCL/DDL)事务日志影响触发器行为空间回收四个方面进行区分。
  2. 索引结构:聚集索引(Clustered Index)与非聚集索引(Non-Clustered Index)在物理存储结构上的核心区别是什么?一个表最多能建立几个聚集索引?非聚集索引的叶子节点存储的是什么?
  3. 排名窗口函数:请详细对比 ROW_NUMBER()RANK()DENSE_RANK() 在处理并列(Ties)情况时的序号生成逻辑差异,并举例说明。
  4. SQL 编程题:编写一条 SQL 查询语句,使用窗口函数 DENSE_RANK() 查询 Employee 表中**第 N 高(例如第 3 高)**的薪水。

第四部分:编码实现题(手写代码)

  1. 算法题(字符串):编写一个 C# 方法,输入一个字符串,统计其中每个字符出现的次数,并最终仅打印出现过的唯一字符(去重)。要求不重复输出相同的字符。
  2. 算法题(矩阵):编写一个 C# 方法,实现给定二维矩阵(M x N)的转置操作,即将行转换为列,列转换为行。输入为 3x3 示例 [[1,2,3],[4,5,6],[7,8,9]],请输出转置后的矩阵。

第五部分:.NET 运行时与内存管理(GC)

  1. 垃圾回收机制:简述 .NET 中的垃圾回收(GC)机制。请分别解释第 0 代、第 1 代和第 2 代(Generations 0, 1, 2)的作用,以及 GC 触发升级的条件。
  2. 确定性资源释放IDisposable 接口的作用是什么?标准的 Dispose(bool disposing) 模式是如何实现托管和非托管资源的统一释放的?

第六部分:工程实践与生产问题排查

  1. 代码审查(PR):在 Pull Request 代码审查中,你通常会关注哪些核心维度?(提示:代码规范、设计模式、潜在性能瓶颈、异常处理、单元测试覆盖等)
  2. 质量定义:你如何定义“高质量的代码”(Quality Code)?请列举你认为最重要的 3~5 个衡量指标。
  3. 环境不一致排查:假设代码在本地 Debug 环境运行完全正常,但部署到生产环境(Release 模式)后出现诡异 Bug,你会按照什么思维导图(步骤)去定位问题?(请考虑环境变量、配置文件、日志级别、框架版本差异等)

参考答案(按题号对应)

1. 使用显式接口实现(Explicit Interface Implementation)。语法为 void IInterfaceA.Method()void IInterfaceB.Method()。调用时,必须将实例转换为对应的接口类型((IInterfaceA)obj.Method())才能调用,若使用类实例直接调用则无法访问显式实现的方法。

2.ref:变量在传入前必须被初始化,方法可读取并修改它。out:变量在传入前可以不初始化,方法在返回前必须为 out 参数赋值out 常用于返回多个值(如 TryParse)。

3.String 是**不可变(Immutable)引用类型,每次修改(拼接、替换)都会在堆上产生新对象,原有对象等待 GC,适合少量操作。StringBuilder可变(Mutable)**类型,维护一个字符缓冲区,适合频繁拼接修改(循环内),性能远优于 String

4. 静态构造函数无访问修饰符(默认 private),无参数,由 CLR 在第一次加载类(访问静态成员或创建实例)之前自动且只调用一次。它先于任何实例构造函数执行。

5. 委托本质上是类型安全的函数指针,派生自 System.MulticastDelegate。多播特性指一个委托实例可以引用多个方法(使用 += 合并),调用时会按顺序执行调用列表中的所有方法。

6.Finalize(终结器,即 ~ClassName())由 GC 自动在回收时调用,非确定性,不保证立即执行。Dispose 由开发者显式调用,确定性释放资源,通常配合 using 语句。标准做法是实现 Dispose 释放托管/非托管资源,并调用 GC.SuppressFinalize 抑制冗余的终结器开销。

7. ① 计算类型及其父类字段所占字节数;② 从托管堆分配内存(含对象头 SyncBlockIndex 和类型指针 MethodTablePointer);③ 初始化对象附加成员(SyncBlockIndex 置 0,TypeHandle 指向类型);④ 调用实例构造函数(依次从基类构造到派生类)。

8. 运行时多态:当基类引用指向子类对象时,调用的方法由实际堆上的对象类型决定(即子类 override 的方法),而非编译时的引用类型。示例:

Base b = new Derived(); b.Method(); // 输出 Derived.Method (如果 Method 是 virtual/override)

base.Method() 在子类重写中显式调用父类实现。

9. 引用类型变量存储的是堆内存地址。赋值操作拷贝的是地址。若 objA = objB,两者指向同一对象。若随后 objA = new MyClass()objA 指向新地址,objB 不受影响,仍指向原对象。若修改 objA 的属性(而非重新赋值),objB 的属性会同步变化。

10. DI 是实现控制反转(IoC)的一种设计模式。构造函数注入强制依赖可见性,对象一旦创建其依赖便不可变,推荐使用。属性注入可选且可变,适合非必要依赖或需要修改依赖的场景(如单元测试中的 Mock)。

11. 中间件按添加顺序组成管道(Request Delegate)。请求进入时按从前到后执行,响应返回时按从后到前执行(若调用了 _next())。Use 可以调用下一个中间件,Run 是终结点(不调用 next)。

12. AuthN(认证)是“你是谁”(如登录验证用户名密码,生成 JWT Token)。AuthZ(授权)是“你能做什么”(如角色 [Authorize(Roles="Admin")] 或策略 [Authorize(Policy="CanEdit")])。授权基于认证结果。

13.JWT Bearer 认证;② 输入验证[ApiController] + 模型校验);③ CORS 策略限制可信域名;④ 强制 HTTPSAddHttpsRedirection);⑤ 防 CSRF(同源/双提交 Cookie,若非浏览器 SPA 需考虑)及敏感数据脱敏/限流

14. Transient(每次获取新实例)、Scoped(同请求/作用域内共享)、Singleton(全局单例)。AddDbContext 默认注册为 Scoped,因为 EF Core 上下文应遵循工作单元模式,且不是线程安全的,需随请求生命周期回收。

15. SOAP 基于 XML,严格规范(WSDL),支持复杂安全标准(WS-Security),传输层无关(HTTP/SMTP)。REST 基于 HTTP(通常 JSON),轻量灵活,利用 HTTP 动词(GET/POST/PUT/DELETE),无状态。现代微服务更倾向 REST。

**16.**DELETE(DML)可带 WHERE,逐行删除,记录日志,触发触发器,空间不立即释放。TRUNCATE(DDL)不可带条件,删除所有页,日志量小,不触发行触发器,重置 Identity,空间释放给对象。DROP(DDL)直接删除整个表结构和数据,回收所有空间。

17.聚集索引:叶子节点存整行数据,表内数据物理顺序与索引顺序一致,一个表只能有一个。非聚集索引:叶子节点存索引键值+聚集索引键(或行定位器),需回表(Lookup)查询数据,一个表可建多个。

18. 假设工资均为 1000 的并列第一。

  • ROW_NUMBER():给行编连续唯一序号(1,2,3,...),并列时随机排先后。
  • RANK():产生不连续序号(1,1,3)——并列共享,跳过下一位。
  • DENSE_RANK():产生连续序号(1,1,2)——并列共享,不跳过。

19.

SELECT SalaryFROM (    SELECT Salary, DENSE_RANK() OVER (ORDER BY Salary DESC) AS RNK    FROM Employee) TWHERE RNK = N; -- 例如 N=3

20.

public static void PrintUniqueChars(string input){    var dict = new Dictionary<char, int>();    foreach (char c in input)         dict[c] = dict.TryGetValue(c, out int count) ? count + 1 : 1;        foreach (var kv in dict)         Console.WriteLine($"{kv.Key}"); // 只打印键,不打印次数实现"不重复"}

21.

public static int[,] Transpose(int[,] matrix){    int rows = matrix.GetLength(0), cols = matrix.GetLength(1);    int[,] result = new int[cols, rows];    for (int i = 0; i < rows; i++)        for (int j = 0; j < cols; j++)            result[j, i] = matrix[i, j];    return result;}

22. GC 采用**分代(Generational)**策略:

  • 第 0 代:新分配的对象,回收频率最高(发生 GC 时清理)。
  • 第 1 代:逃过 1 次 0 代 GC 的对象(晋升)。
  • 第 2 代:逃过多次 GC 的大对象(LOH 直接进 2 代)或长久存活对象。GC 会自动调整各代阈值。

23.IDisposable 接口定义 Dispose() 方法,用于提前释放非托管资源(如文件句柄、数据库连接、GDI 资源)。标准模式是 Dispose(bool disposing)disposing=true 时释放托管资源并调用基类 Dispose;disposing=false 时仅释放非托管资源(由终结器调用)。

24. 关注点:① 业务逻辑正确性;② 异常处理与日志记录是否完善;③ 性能(有无 N+1 查询、循环操作 DB);④ 安全性(SQL 注入、敏感信息泄露);⑤ 可维护性(命名规范、注释、单一职责);⑥ 单元测试是否同步更新

25. 高质量代码标准:① 可读性(自解释、遵循命名规范);② 可维护性/可扩展性(低耦合高内聚,遵循 OCP 开闭原则);③ 鲁棒性(优雅处理边界条件和异常);④ 高性能;⑤ 单元测试覆盖率达标。

26. 排查步骤:① 检查配置文件差异(appsettings.Production.jsonappsettings.Development.json);② 核对环境变量(ASPNETCORE_ENVIRONMENT);③ 比对日志级别(Production 可能关闭了 Debug 日志导致信息丢失,需开启 Info 日志);④ 确认数据库连接字符串权限及迁移是否执行;⑤ 检查依赖的第三方服务/缓存可用性;⑥ 对比 TargetFramework 或 SDK 版本在生产与本地是否一致。

注:答案仅供参考

关注公众号↑↑↑:DotNet开发跳槽❀    

关于本站

记录一个程序员的日常:踩坑、复盘、工具与随想。内容支持从公众号一键抓取导入。