C#高级特性面试问题的详细分析,涵盖核心概念、应用场景和最佳实践

序列化与反序列化

1. 什么是序列化和反序列化?用途是什么?

// 序列化示例
Person person = new Person { Name = "Alice", Age = 30 };
string json = JsonSerializer.Serialize(person); // 序列化为JSON// 反序列化示例
Person deserialized = JsonSerializer.Deserialize<Person>(json);
  • 核心概念
    • 序列化:将对象状态转换为可存储/传输格式(如JSON、XML、二进制)
    • 反序列化:将数据流还原为对象
  • 关键用途
    • 网络传输(API通信)
    • 数据持久化(保存到文件/数据库)
    • 进程间通信
    • 缓存机制

2. JSON vs XML 序列化的优缺点

特性JSONXML
可读性高(轻量级)中(标签冗余)
数据体积小(无标签)大(标签占40%+空间)
解析性能快(比XML快2-10倍)慢(DOM解析复杂)
类型安全弱(无schema)强(XSD支持)
二进制支持Base64编码原生支持(CDATA)
适用场景Web API、移动应用企业系统、SOAP服务

3. 循环引用处理

// Newtonsoft.Json解决方案
var settings = new JsonSerializerSettings {ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
string json = JsonConvert.SerializeObject(obj, settings);// System.Text.Json解决方案
options.ReferenceHandler = ReferenceHandler.Preserve;
  • 根本原因:对象相互引用形成闭环(如 Parent.ChildChild.Parent
  • 解决方案
    1. 忽略循环引用(ReferenceLoopHandling.Ignore
    2. 使用[JsonIgnore]标记属性
    3. DTO模式(仅序列化必要数据)
    4. 自定义ID追踪(PreserveReferencesHandling

4. 自定义序列化

// 实现ISerializable接口
[Serializable]
public class CustomObject : ISerializable
{public void GetObjectData(SerializationInfo info, StreamingContext context){info.AddValue("customField", _value);}protected CustomObject(SerializationInfo info, StreamingContext context){_value = info.GetString("customField");}
}// JSON自定义转换器
public class DateTimeConverter : JsonConverter<DateTime>
{public override DateTime Read(ref Utf8JsonReader reader, ...) => DateTime.Parse(reader.GetString());public override void Write(Utf8JsonWriter writer, DateTime value, ...)=> writer.WriteStringValue(value.ToString("yyyy-MM-dd"));
}

5. 版本控制策略

  • 向前兼容
    • 使用[OptionalField]特性
    • 反序列化回调(OnDeserializing
  • 向后兼容
    • 避免删除已序列化字段
    • 新字段添加默认值
  • 最佳实践:
    • 语义版本控制(SemVer)
    • 自定义版本字段
    • 使用协议缓冲区(protobuf)等版本容忍格式

泛型

1. 泛型核心优势

// 类型安全集合
List<string> strings = new List<string>();
strings.Add("text");  // 编译时类型检查
// strings.Add(42);   // 编译错误// 避免装箱
List<int> numbers = new List<int>(); // 无装箱开销
  • 三大优势
    1. 编译时类型检查
    2. 消除装箱/拆箱(值类型性能提升20-50%)
    3. 代码复用(同一算法处理不同类型)

2. 泛型约束类型

public class Processor<T> where T : IComparable,      // 接口约束new(),            // 构造函数约束struct            // 值类型约束
{public void Sort(T[] data) { /*...*/ }
}
约束类型语法应用场景
接口约束where T : IDisposable确保类型实现特定行为
基类约束where T : Stream限制继承层次
构造函数约束where T : new()创建实例(new T()
值类型/引用类型约束where T : struct优化值类型操作
非托管约束where T : unmanaged不安全代码/指针操作

3. 协变(in)与逆变(out)

// 协变:子类→父类 (out)
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;  // 安全// 逆变:父类→子类 (in)
Action<object> logObject = obj => Console.Write(obj);
Action<string> logString = logObject;  // 安全
logString("text");  // 实际执行logObject
  • 核心规则
    • 协变(out):返回值类型,支持更具体的子类型
    • 逆变(in):参数类型,支持更通用的父类型
    • 只适用于接口和委托

4. 泛型与反射交互

// 创建泛型类型实例
Type openType = typeof(Dictionary<,>);
Type closedType = openType.MakeGenericType(typeof(int), typeof(string));
object dict = Activator.CreateInstance(closedType);// 调用泛型方法
MethodInfo method = typeof(Serializer).GetMethod("Serialize");
MethodInfo closedMethod = method.MakeGenericMethod(typeof(Person));
closedMethod.Invoke(null, new object[] { person });

5. 泛型接口设计模式

public interface IRepository<TEntity, TKey> where TEntity : IEntity<TKey>
{TEntity GetById(TKey id);void Add(TEntity entity);
}public class UserRepository : IRepository<User, int> 
{public User GetById(int id) { /* DB查询 */ }public void Add(User entity) { /* DB插入 */ }
}

集合

1. List vs Array

// Array - 固定大小
int[] array = new int[10]; 
array[0] = 1; // 赋值
// array[10] = 1; // 运行时越界错误// List<T> - 动态扩展
List<int> list = new List<int>(capacity: 100);
list.Add(1); // 自动扩容
list.RemoveAt(0); // 动态收缩
特性ArrayList
大小固定动态扩展
内存分配连续块动态数组+缓冲池
插入/删除性能O(n)O(n)(尾部O(1))
随机访问O(1)O(1)
线程安全

2. Dictionary工作原理

var dict = new Dictionary<string, int>();
dict.Add("key1", 42); // 内部实现伪代码:
// 1. 计算哈希:key.GetHashCode() -> bucketIndex
// 2. 处理冲突:链地址法(链表存储冲突项)
// 3. 存储键值对:entries[bucketIndex] = new Entry(key, value)
  • 哈希冲突解决方案
    • 开放寻址法(.NET Core+)
    • 链地址法(.NET Framework)
  • 时间复杂度
    • 查找/插入/删除:平均O(1),最坏O(n)
  • 最佳实践
    • 实现GetHashCode()Equals()的规范重写
    • 设置合理初始容量减少扩容

3. 集合接口层次

IEnumerable
ICollection
IList
ISet
IQueryable
  • 核心接口
    • IEnumerable<T>:基本迭代(GetEnumerator
    • ICollection<T>:添加/删除(Count, Add, Remove
    • IList<T>:索引访问(this[index], Insert
    • ISet<T>:集合操作(UnionWith, IntersectWith

4. 自定义集合实现

public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged
{protected override void InsertItem(int index, T item){base.InsertItem(index, item);OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);}protected virtual void OnCollectionChanged(...) => CollectionChanged?.Invoke(this, args);
}
  • 继承Collection<T>基类
  • 重写关键方法:InsertItem, SetItem, RemoveItem
  • 实现通知机制(如INotifyCollectionChanged

5. 线程安全集合

// 并发字典
var concurrentDict = new ConcurrentDictionary<string, int>();
concurrentDict.TryAdd("key", 42);// 生产者-消费者队列
BlockingCollection<int> queue = new BlockingCollection<int>();
// 生产者
queue.Add(1);  
// 消费者
int item = queue.Take(); 
集合类型适用场景
ConcurrentDictionary高频读/写的键值存储
ConcurrentQueue任务队列(生产者-消费者)
ConcurrentBag无序对象池
BlockingCollection有界/无界阻塞队列

Lambda表达式

1. Lambda vs 匿名方法

// 匿名方法(C# 2.0)
Func<int, int> square = delegate(int x) { return x * x; };// Lambda表达式(C# 3.0+)
Func<int, int> square = x => x * x;
特性匿名方法Lambda表达式
语法简洁性冗长简洁
参数类型推断需显式声明可推断
表达式树支持不支持支持
闭包支持支持支持
单行返回值需return语句自动返回

2. 闭包与变量捕获

int factor = 2;
Func<int, int> multiplier = x => x * factor;
Console.WriteLine(multiplier(5)); // 10// 修改捕获变量
factor = 3;
Console.WriteLine(multiplier(5)); // 15
  • 闭包原理
    • 编译器生成隐藏类(closure类)
    • 捕获变量转为类的字段
    • Lambda成为实例方法
  • 陷阱
    • 循环变量捕获问题(所有迭代共享同一变量)
    • 解决方案:循环内声明临时变量

3. 表达式树(Expression Trees)

Expression<Func<int, bool>> expr = x => x > 5 && x < 10;// 解析表达式树
BinaryExpression body = (BinaryExpression)expr.Body;
ParameterExpression param = (ParameterExpression)expr.Parameters[0];
  • 核心特性
    • 将代码转为可遍历的数据结构
    • LINQ to SQL等ORM的核心技术
  • 应用场景
    • 动态SQL生成
    • 运行时条件组合
    • 自定义查询翻译

4. 变量作用域规则

int outer = 10;
Action action = () => 
{int inner = 20;Console.WriteLine(outer + inner); // 访问外部变量
};
// Console.WriteLine(inner); // 错误:inner不可访问
  • 作用域层次
    1. Lambda参数
    2. Lambda内部声明
    3. 外部方法变量
    4. 类成员变量
  • 生命周期
    • 捕获变量的生命周期延至所有委托被GC回收

5. Lambda性能优化

// 避免:高频调用中重复编译表达式树
Expression<Func<Person, bool>> expr = p => p.Age > 18;
Func<Person, bool> compiled = expr.Compile(); // 缓存此委托// 优先使用静态Lambda(C# 9.0+)
Func<int, int> square = static x => x * x; // 不捕获上下文
  • 优化策略:
    • 缓存编译后的委托
    • 避免在高频循环中捕获变量
    • 使用静态Lambda减少内存分配
    • 避免深层嵌套的Lambda

LINQ

1. 延迟执行 vs 立即执行

// 延迟执行(未真正执行)
IEnumerable<int> query = data.Where(x => x > 5);// 触发执行的操作:
var list = query.ToList();      // 立即执行
int count = query.Count();      // 立即执行
var first = query.First();      // 立即执行// 流式执行(yield return)
foreach (var item in query)     // 遍历时逐步执行
{// 每次迭代处理一个元素
}

2. Select vs SelectMany

// Select:一对一转換
var names = persons.Select(p => p.Name);// SelectMany:集合展开
var allPhones = persons.SelectMany(p => p.Phones);// 模拟SQL JOIN
var orders = customers.SelectMany(c => c.Orders,(customer, order) => new { customer.Name, order.Id }
);

3. LINQ性能优化

// 数据库查询优化
var results = context.Users.Where(u => u.Age > 18)    // 在数据库执行.AsNoTracking()             // 禁用变更追踪.Select(u => new { u.Name }) // 仅选择必要字段.ToList();// 内存集合优化
var local = data.Where(x => x.IsActive).OrderBy(x => x.Name)     // 先过滤再排序.Take(20)                 // 尽早限制数量.ToList();
  • 关键优化点
    • 数据库:使用投影减少数据传输
    • EF Core:AsNoTracking()用于只读查询
    • 内存:避免N+1查询模式
    • 使用Any()替代Count() > 0

4. IQueryable vs IEnumerable

// IEnumerable - 客户端执行
var result = context.Users.AsEnumerable()            // 切换为客户端评估.Where(u => ComplexLogic(u)); // 在内存中执行// IQueryable - 数据库执行
var result = context.Users.Where(u => u.Age > 18)    // 转换为SQL.ToList();                 // 在数据库执行
特性IEnumerableIQueryable
执行位置客户端内存数据源(如数据库)
查询能力LINQ to Objects支持提供程序翻译(如SQL)
延迟执行支持支持
性能特点适合内存数据集减少数据传输量

5. 自定义LINQ提供程序

public class CustomQueryable<T> : IQueryable<T>
{public Type ElementType => typeof(T);public Expression Expression { get; }public IQueryProvider Provider { get; }// 实现GetEnumerator和必要接口
}public class CustomProvider : IQueryProvider
{public IQueryable CreateQuery(Expression expression) { ... }public object Execute(Expression expression){// 解析表达式树var translator = new CustomTranslator();translator.Visit(expression);// 执行自定义查询逻辑return ExecuteDatabaseQuery(translator.GetQuery());}
}
  • 实现步骤
    1. 实现IQueryableIQueryProvider
    2. 解析表达式树(ExpressionVisitor
    3. 转换为目标查询语言(如SQL)
    4. 执行查询并映射结果
  • 难点
    • 表达式树的完整解析
    • 参数化查询处理
    • 嵌套查询支持

综合问题深度分析

1. 泛型+集合+LINQ综合应用

public class DataService<T> where T : class
{public List<T> FilterAndSort(List<T> data, Func<T, bool> filter,Func<T, object> sorter){return data.Where(filter).OrderBy(sorter).ToList();}
}// 使用
var userService = new DataService<User>();
var activeUsers = userService.FilterAndSort(users, u => u.IsActive, u => u.LastLoginDate
);

2. 多格式序列化服务

public interface ISerializer<T>
{string Serialize(T obj);T Deserialize(string data);
}public class JsonSerializer<T> : ISerializer<T> { /*...*/ }
public class XmlSerializer<T> : ISerializer<T> { /*...*/ }public class SerializationService<T>
{private readonly ISerializer<T> _serializer;public SerializationService(ISerializer<T> serializer) => _serializer = serializer;public string ToString(T obj) => _serializer.Serialize(obj);public T FromString(string data) => _serializer.Deserialize(data);
}

3. 表达式树工作原理

Lambda表达式
表达式树
表达式树节点
参数表达式
二元表达式
常量表达式
查询提供程序
翻译机制
SQL查询
数据库执行

4. 大型数据集处理策略

// 流式JSON反序列化
await using var stream = File.OpenRead("large.json");
var data = JsonSerializer.DeserializeAsyncEnumerable<Person>(stream);await foreach (var person in data)
{// 单条处理,内存占用恒定
}// 分块处理
const int chunkSize = 1000;
for (int i = 0; i < data.Count; i += chunkSize)
{var chunk = data.Skip(i).Take(chunkSize);ProcessChunk(chunk);
}

5. Lambda实现策略模式

public class PaymentProcessor
{private Func<Order, PaymentResult> _paymentStrategy;public void SetPaymentStrategy(Func<Order, PaymentResult> strategy) => _paymentStrategy = strategy;public PaymentResult ProcessOrder(Order order)=> _paymentStrategy?.Invoke(order) ?? throw new InvalidOperationException();
}// 使用
var processor = new PaymentProcessor();
processor.SetPaymentStrategy(order => order.Total > 1000 ? ProcessCreditCard(order) : ProcessCash(order));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/88453.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/88453.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【电脑】内存的基础知识

内存&#xff08;Memory&#xff09;是计算机中用于临时存储数据和程序的地方&#xff0c;它直接影响到系统的运行速度和性能。以下是关于内存的详细知识&#xff1a;1. 内存类型常见的内存类型包括以下几个主要种类&#xff1a;SDRAM (Synchronous Dynamic Random Access Memo…

Java---IDEA

IDEA概述 IDEA&#xff1a;全称Intellij IDEA&#xff0c;是用于Java语言开发的集成开发环境 集成环境&#xff1a;把代码编写&#xff0c;编译&#xff0c;运行&#xff0c;调试等多种功能综合到一起的开发工具 下载与安装 下载&#xff1a;IntelliJ IDEA – the IDE for …

【每日刷题】x 的平方根

69. x 的平方根 - 力扣&#xff08;LeetCode&#xff09; 方法一&#xff1a;暴力 从0开始遍历&#xff0c;直到 ans*ans > x 为止&#xff0c;这时ans-1就是答案。需要注意可能会爆int&#xff0c;所以ans要开为long&#xff0c;最后再转换为int。 class Solution {publ…

C#元组:从基础到实战的全方位解析

C#元组&#xff1a;从基础到实战的全方位解析 在 C# 编程中&#xff0c;元组&#xff08;Tuple&#xff09;是一种轻量级的数据结构&#xff0c;用于临时存储多个不同类型的元素。无论是方法返回多个值、LINQ 查询中的临时投影&#xff0c;还是简化数据传递&#xff0c;元组都以…

Django母婴商城项目实践(二)

2、母婴商城项目环境配置 环境配置: Python3.12 解释器Pycharm Professional 2025.1 编辑器Django 4.2(或 Django 5.x)MySQL 8.0.28 数据库 1、Django框架 介绍 Django是一个高级的Python Web应用框架,可以快速开发安全和可维护的网站。由经验丰富的开发者构建,Django负责…

Go语言的Channel通道的含义。区分缓冲通道和非缓冲通道,并讨论通道的发送、接收、关闭以及如何安全地从已关闭的通道读取数据。

非缓冲通道&#xff1a;非缓冲通道在确定时没有声明容量大小&#xff0c;发送和接收操作会同步阻塞&#xff0c;直到另一端准备好。发送方和接收方必须同时就绪才能完成数据交换&#xff0c;否则会阻塞。常用于goroutine之间的同步通信。缓冲通道&#xff1a;缓冲通道在确定时就…

tensor

&#x1f609;如果您想用jupyter notebook跑我的笔记&#xff0c;可以在下面获取ipynb版本 &#x1f60a;麻烦给个免费的star&#x1f618; ❤️主包也更建议这种形式&#xff0c;上面的笔记也更加全面&#xff0c;每一步都有直观的输出 文章目录&#x1f4da; PyTorch张量操作…

STM32-DAC数模转换

DAC数模转换&#xff1a;将数字信号转换成模拟信号特性&#xff1a;2个DAC转换器每个都拥有一个转换通道8位或12位单调输出&#xff08;8位右对齐&#xff1b;12位左对齐右对齐&#xff09;双ADC通道同时或者分别转换外部触发中断电压源控制部分&#xff08;外部触发3个APB1&am…

前后端集合如何传递

前端vue后端rest风格&#xff1a;1.路径传参&#xff08;参数必传&#xff09;&#xff0c;通过pathvarible注解后端&#xff1a;DeleteMapping("/{YYIDs}")public R<Void> remove(NotEmpty(message "主键不能为空")PathVariable String[] YYIDs) {…

1353. 最多可以参加的会议数目

1353. 最多可以参加的会议数目 题目链接&#xff1a;1353. 最多可以参加的会议数目 代码如下&#xff1a; class Solution { public:int maxEvents(vector<vector<int>>& events) {int mx 0;for (auto& e : events) {mx max(mx, e[1]); // 找到最大的结…

OCR 本地版本

UMI OCR 支持本地部署&#xff0c;支持HTTP OCR

大数据驱动的酒店用品需求预测模型研究 开发——毕业论文,毕业设计——仙盟创梦IDE

主页酒店用品 平台协议促销毕业论文摘要本研究旨在构建基于大数据分析的酒店用品需求预测模型&#xff0c;以提高酒店用品批发企业的库存管理效率和供应链响应速度。研究整合了酒店历史采购数据、季节因素、市场趋势、节假日信息等多源数据&#xff0c;通过对比传统时间序列模型…

Windows11桌面解锁守护脚本

使用python程序加bat一键运行脚本&#xff0c;妈妈再也不用担心我的电脑桌面了import os import time import cv2 import pyautogui import psutil from datetime import datetimeclass UnlockMonitor:def __init__(self):"""初始化监控器"""sel…

Linux Ubuntu系统的用户管理

一.关于root用户默认我们安装完系统后 注册的用户就是管理员用户标识符 $ 管理员标识符#最高管理员在Ubuntu系统中,root是最高管理员,拥有最大的权限,默认情况下root用户没有启用密码,而是通过sudo机制来获取管理员权限二.Ubuntu系统中root用户的默认状态root用户存在,但未启用…

ROS1学习第三弹

ROS1学习第二弹 本文纯属记录学习过程&#xff0c;所学教程来自B站古月居ROS入门21讲 tf工具的使用 命令行中 1.rosrun tf view_frames 生成当前各个坐标的结构图&#xff0c;导出pdf文件到当前终端所在文件夹下面2.rosrun rviz rviz -d rospackage find turtle_tf /rviz/tu…

技术演进中的开发沉思-30 MFC系列:五大机制

MFC&#xff0c;记得我刚毕业时在 CRT 显示器前敲下第一行 MFC 代码时&#xff0c;那时什么都不懂&#xff0c;没有框架的概念。只觉得眼前的 CObject 像位沉默且复杂的大家族&#xff0c; 就像老北京胡同里的大家族&#xff0c;每个门牌号都藏着自己的故事。但现在看看&#x…

机器学习-06(Optimization-自动调整学习率)

临界点其实不一定是在训练神经网络过程中遇到的最大阻碍。随着对参数的不断更新&#xff0c;Loss值会不断下降&#xff0c;直至几乎没有变化&#xff0c;不再下降。当参数更新到临界点时&#xff0c;意味着gradient非常小&#xff0c;所以要认定参数是否到达临界点应当确认grad…

Uniapp中的uni.scss

uni.scss为uni-app新建项目自带工程文件&#xff0c;使用的预处理器为sass/scss&#xff0c;由此可见&#xff0c;uni-app官方推荐的是scss。 uni.scss特点 无需引入&#xff0c;uni-app在编译时&#xff0c;会自动引入此文件在此中定义的scss变量&#xff0c;可以全局使用&…

PreparedStatement 实现分页查询详解

PreparedStatement 实现分页查询详解 在 JDBC 中使用 PreparedStatement 实现分页查询是高效安全的方式&#xff0c;可以避免 SQL 注入并提升性能。下面我将详细说明实现步骤和原理。 &#x1f4d0; 分页查询核心参数参数名说明计算公式pageNum当前页码&#xff08;从1开始&…

ClamAV 和 FreshClam:Linux 服务器上的开源杀毒解决方案

ClamAV 和 FreshClam:Linux 服务器上的开源杀毒解决方案 1. 概述 ClamAV 是一款开源的防病毒引擎,专为 Linux 服务器设计,用于检测恶意软件、病毒、木马和其他安全威胁。它广泛应用于邮件服务器、文件存储系统和 Web 服务器,提供高效的病毒扫描功能。 主要特点: 免费开…