C#面试题及详细答案120道(116-120)-- 综合应用
《前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux… 。

文章目录
- 一、本文面试题目录
- 116. 如何实现深拷贝和浅拷贝?
- 117. 如何序列化和反序列化对象?(XmlSerializer、JsonSerializer等)
- 118. 什么是RESTful API?如何用ASP.NET Core实现?
- 119. 如何处理C#中的日期时间(DateTime、DateTimeOffset)?
- 120. 简述你在项目中使用C#解决的一个复杂问题及方案
- 二、120道C#面试题目录列表
一、本文面试题目录
116. 如何实现深拷贝和浅拷贝?
-
原理说明:
拷贝是创建对象副本的操作,分为两种类型:- 浅拷贝(Shallow Copy):只复制对象本身及值类型字段,引用类型字段仅复制引用(副本与原对象共享引用类型数据)。
- 深拷贝(Deep Copy):完全复制对象及所有嵌套的引用类型数据,副本与原对象无共享数据,彼此独立。
-
实现方式:
-
浅拷贝:
- 实现
ICloneable接口,在Clone()方法中使用MemberwiseClone()(Object类的保护方法,用于浅拷贝)。
- 实现
-
深拷贝:
- 序列化与反序列化(将对象转换为字节流再还原,适合复杂对象)。
- 手动递归复制所有字段(包括引用类型)。
-
-
示例代码:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;// 示例类(包含引用类型)
public class Address
{public string City { get; set; }
}public class Person : ICloneable
{public string Name { get; set; } // 值类型性质(string是特殊引用类型,但行为类似值类型)public Address Address { get; set; } // 引用类型// 浅拷贝实现public object Clone(){return MemberwiseClone(); // 浅拷贝:Address字段仅复制引用}// 深拷贝实现(基于序列化)public Person DeepClone(){using (var stream = new MemoryStream()){var formatter = new BinaryFormatter();formatter.Serialize(stream, this);stream.Position = 0;return (Person)formatter.Deserialize(stream);}}
}// 使用示例
class Program
{static void Main(){var person = new Person{Name = "Alice",Address = new Address { City = "Beijing" }};// 浅拷贝:修改副本的Address会影响原对象var shallowCopy = (Person)person.Clone();shallowCopy.Address.City = "Shanghai";Console.WriteLine(person.Address.City); // 输出:Shanghai(原对象被修改)// 深拷贝:副本与原对象完全独立var deepCopy = person.DeepClone();deepCopy.Address.City = "Guangzhou";Console.WriteLine(person.Address.City); // 输出:Shanghai(原对象不受影响)}
}
117. 如何序列化和反序列化对象?(XmlSerializer、JsonSerializer等)
-
原理说明:
序列化是将对象转换为可传输或存储的格式(如XML、JSON、二进制),反序列化则是将其还原为对象。常用于数据传输(如API通信)、持久化存储等场景。 -
常用序列化方式:
- JSON序列化(System.Text.Json):.NET Core 3.0+内置,轻量高效,适合Web API。
- XML序列化(XmlSerializer):传统XML格式,支持复杂类型和属性配置。
- 二进制序列化(BinaryFormatter):已过时(安全性问题),不推荐使用,可替代为
System.Runtime.Serialization.Formatters.Binary或第三方库。
-
示例代码:
using System;
using System.IO;
using System.Text.Json;
using System.Xml.Serialization;// 待序列化的类
public class Book
{public int Id { get; set; }public string Title { get; set; }public DateTime PublishDate { get; set; }
}class Program
{static void Main(){var book = new Book{Id = 1,Title = "C# Guide",PublishDate = new DateTime(2023, 1, 1)};// 1. JSON序列化与反序列化(System.Text.Json)string json = JsonSerializer.Serialize(book, new JsonSerializerOptions { WriteIndented = true });Console.WriteLine("JSON:\n" + json);Book bookFromJson = JsonSerializer.Deserialize<Book>(json);// 2. XML序列化与反序列化(XmlSerializer)var xmlSerializer = new XmlSerializer(typeof(Book));using (var writer = new StringWriter()){xmlSerializer.Serialize(writer, book);string xml = writer.ToString();Console.WriteLine("\nXML:\n" + xml);using (var reader = new StringReader(xml)){Book bookFromXml = (Book)xmlSerializer.Deserialize(reader);}}}
}
118. 什么是RESTful API?如何用ASP.NET Core实现?
-
原理说明:
RESTful API是遵循REST(Representational State Transfer)架构风格的API设计规范,核心特点:- 基于HTTP方法(GET/POST/PUT/DELETE)表达操作语义(查询/创建/更新/删除)。
- 使用URL标识资源(如
/api/books表示图书资源集合)。 - 无状态(每个请求包含所有必要信息,服务器不存储客户端状态)。
- 支持多种数据格式(如JSON、XML)。
-
ASP.NET Core实现步骤:
- 创建ASP.NET Core Web API项目。
- 定义控制器(继承
ControllerBase),通过[Route("api/[controller]")]指定路由。 - 用
[HttpGet]、[HttpPost]等[HttpPut]、[HttpDelete]标记记对应HTTP方法的动作。
-
示例代码:
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;// 图书模型
public class Book
{public int Id { get; set; }public string Title { get; set; }
}// 内存控制器控制器(RESTful API)
[Route("api/[controller]")]
[ApiController]
public class BooksController : ControllerBase
{// 模拟数据库private static readonly List<Book> _books = new List<Book>{new Book { Id = 1, Title = "ASP.NET Core Guide" },new Book { Id = 2, Title = "C# Advanced" }};// GET: api/books(查询询所有资源)[HttpGet]public ActionResult<IEnumerable<Book>> GetBooks(){return _books;}// GET: api/books/5(查询单个资源)[HttpGet("{id}")]public ActionResult<Book> GetBook(int id){var book = _books.FirstOrDefault(b => b.Id == id);if (book == null){return NotFound(); // 404 Not Found}return book;}// POST: api/books(创建资源)[HttpPost]public ActionResult<Book> PostBook(Book book){_books.Add(book);return CreatedAtAction(nameof(GetBook), new { id = book.Id }, book); // 201 Created}// PUT: api/books/5(更新资源)[HttpPut("{id}")]public IActionResult PutBook(int id, Book book){if (id != book.Id){return BadRequest(); // 400 Bad Request}var existing = _books.FirstOrDefault(b => b.Id == id);if (existing == null){return NotFound();}existing.Title = book.Title;return NoContent(); // 204 No Content}// DELETE: api/books/5(删除资源)[HttpDelete("{id}")]public IActionResult DeleteBookBook(int id){var book = _books.FirstOrDefault(b => b.Id == id);if (book == null){return NotFound();}_books.Remove(book);return NoContent();}
}
119. 如何处理C#中的日期时间(DateTime、DateTimeOffset)?
-
原理说明:
C#提供两种主要类型处理日期时间:- DateTime:表示具体的日期和时间,可包含本地时间、UTC时间或未指定类型的时间,但不直接存储时区信息,易导致时区转换问题。
- DateTimeOffset:包含日期时间和与UTC的偏移量(如
+08:00),明确表示特定时区的时间,推荐用于跨时区场景。
-
常用操作:
- 创建日期时间:使用构造函数或静态方法(如
DateTime.Now、DateTime.UtcNow)。 - 时区转换:
ToUniversalTime()(转UTC)、ToLocalTime()(转本地时间)。 - 格式化:
ToString("yyyy-MM-dd HH:mm:ss")自定义格式。 - 计算:
AddDays()、Subtract()等方法处理时间间隔。
- 创建日期时间:使用构造函数或静态方法(如
-
示例代码:
using System;class Program
{static void Main(){// 1. DateTime使用DateTime localNow = DateTime.Now; // 本地时间(含系统时区)DateTime utcNow = DateTime.UtcNow; // UTC时间(无时区)Console.WriteLine($"本地时间: {localNow:yyyy-MM-dd HH:mm:ss}");Console.WriteLine.WriteLine($"UTC时间: {utcNow:yyyy-MM-dd-dd HH:mm:ss}");// 时区转换DateTime converted = localNow.ToUniversalTime(); // 本地时间转UTCConsole.WriteLine($"本地转UTC: {converted:yyyy-MM-dd HH:mm:ss}");// 2. DateTimeOffset使用(包含偏移量)DateTimeOffset offsetNow = DateTimeOffset.Now; // 本地时间+偏移量Console.WriteLine($"DateTimeOffset: {offsetNow:yyyy-MM-dd HH:mm:ss zzz}");Console.WriteLine($"对应的UTC时间: {offsetNow.UtcDateTime:yyyy-MM-dd HH:mm:ss}");// 3. 时间计算DateTime tomorrow = DateTime.Now.AddDays(1);TimeSpan diff = tomorrow - DateTime.Now;Console.WriteLine($"距离明天还有: {diff.TotalHours} 小时");// 4. 解析字符串为DateTimeif (DateTime.TryParse("2023-12-31", out DateTime date)){Console.WriteLine($"解析的日期: {date:yyyy年MM月dd日}");}}
}
120. 简述你在项目中使用C#解决的一个复杂问题及方案
-
问题场景:
某电商平台需处理大量并发订单提交,存在以下挑战:- 高并发场景下库存超卖(多个个用户同时时购买最后一件商品)。
- 订单创建需需调用多个外部服务(支付、物流、通知),任一服务失败需回滚整个流程。
- 需处理大量订单数据,需保证系统响应速度。
-
解决方案:
-
解决决库存超卖:
- 使用数据库事务+行级锁(
SELECT ... FOR UPDATE)确保库存检查和扣减的原子性。 - 结合
Interlocked类实现内存级别的库存预扣减,减少数据库压力。
- 使用数据库事务+行级锁(
-
分布式事务与补偿机制:
- 采用“本地消息表+定时任务”实现最终一致性(替代复杂的分布式事务)。
- 每个服务步骤记录状态,某服务调用失败时执行补偿操作(如恢复库存、取消支付)。
-
性能优化:
- 使用
ConcurrentDataReader批量读取订单数据,减少内存占用。 - 订单创建逻辑异步化(
async/await),避免线程阻塞。 - 引入Redis缓存热门商品库存,减少数据库查询。
- 使用
-
-
核心代码示例:
// 库存扣减(防超卖)
public async Task<bool> DeductInventoryAsync(int productId, int quantity)
{using (var connection = new SqlConnection(_connectionString)){await connection.OpenAsync();using (var transaction = connection.BeginTransaction()){try{// 行级锁查询库存var inventory = await connection.QueryFirstOrDefaultAsync<int>("SELECT Stock FROM Products WHERE Id = @Id FOR UPDATE",new { Id = productId }, transaction);if (inventory < quantity){transaction.Rollback();return false; // 库存不足}// 扣减库存await await connection.ExecuteAsync("UPDATEDATE Stock = Stock - @Quantity WHERE Id = @Id",new { Id = productId, Quantity = quantity }, transaction);transaction.Commit();return true;}catch{transaction.Rollback();throw;}}}
}// 订单创建(含补偿机制)
public async Task CreateOrderAsync(Order order)
{// 记录本地消息(用于后续补偿)var message = new LocalMessage { OrderId = order.Id, Status = "Pending" };_dbContext.LocalMessages.Add(message);await _dbContext.SaveChangesAsync();try{// 1. 扣减库存bool inventoryDeducted = await DeductInventoryAsync(order.ProductId, order.Quantity);if (!inventoryDeducted) throw new Exception("库存不足");// 2. 调用支付服务await _paymentService.PayAsync(order);// 3. 调用物流服务await _logisticsService.CreateShipmentAsync(order);// 4. 更新消息状态为成功message.Status = "Completed";await _dbContext.SaveChangesAsync();}catch (Exception ex){// 标记消息为失败,等待补偿任务处理message.Status = "Failed";message.Error = ex.Message;await _dbContext.SaveChangesAsync();throw;}
}
- 效果:
系统支持每秒1000+订单提交,库存超超超卖现超卖现象,服务失败时自动触发补偿,数据一致性达标。
二、120道C#面试题目录列表
| 文章序号 | C#面试题120道 |
|---|---|
| 1 | C#面试题及详细答案120道(01-10) |
| 2 | C#面试题及详细答案120道(11-20) |
| 3 | C#面试题及详细答案120道(21-30) |
| 4 | C#面试题及详细答案120道(31-40) |
| 5 | C#面试题及详细答案120道(41-50) |
| 6 | C#面试题及详细答案120道(51-60) |
| 7 | C#面试题及详细答案120道(61-75) |
| 8 | C#面试题及详细答案120道(76-85) |
| 9 | C#面试题及详细答案120道(86-95) |
| 10 | C#面试题及详细答案120道(96-105) |
| 11 | C#面试题及详细答案120道(106-115) |
| 12 | C#面试题及详细答案120道(116-120) |
