kitlau
kitlau

kitlau's blog

.NET .NET


如何使用 AnduinOS 愉快的开发 .NET

在Linux系统上开发.NET应用时如何兼顾效率与成本?AnduinOS环境下VSCode的插件生态为开发者提供了新的可能性。通过C#插件与OmniSharp的深度整合,开发者可以在轻量级编辑器中获得智能感知、代码导航等核心功能。当C# Dev Kit带来接近Visual Studio的项目管理能力时,其许可证对商业团队的限制却成为隐性成本。Roslynator作为免费替代方案虽功能精简但内核强大,它基于500+分析器的代码优化能力,恰好映射了JetBrains Rider的开源精神与商业边界。XML文档注释生成器和命名空间自动补全等工具,将日常开发中的机械性操作转化为流畅的创作体验。而GitHub Copilot带来的AI编码革命,正在重新定义开发者对代码生产率的认知边界。当开源工具链与商业软件形成微妙平衡,开发者是否正在经历从IDE依赖向插件生态的范式转移?在AnduinOS的桌面环境下,.NET开发者的生产力工具箱究竟应该包含哪些关键组件?这些选择背后的技术考量与商业权衡,或许正是每个开发者都需要思考的命题。你是否也在寻找更高效的开发方式?--Qwen3

.NET C# VSCode AnduinOS dotnet vscode-plugins github-copilot development-environment

你可能正在写内存泄漏的 .NET 代码!

在.NET开发中,内存泄漏是导致运行时不稳定的重要隐患。本文通过多个代码场景揭示了开发者可能不经意间撰写的危险代码:匿名方法捕获类成员会形成强引用导致对象无法回收,事件订阅若未手动取消订阅则可能因静态事件持有引用而泄漏,静态变量和集合若长期缓存实例会成为GC Root引发内存膨胀,内存缓存若缺乏清理机制会导致数据无限增长,未正确Dispose的非托管资源会消耗额外内存,而unsafe代码和直接内存操作则需要开发者具备清晰的内存管理意识。作者通过JobQueue添加任务、Publisher-Subscriber事件绑定、静态实例集合并发增长等典型示例,展示了内存泄漏的形成机制与修复策略。文章最后抛出值得深思的问题:你是否在代码中使用了静态事件或长期缓存集合?是否在处理流和文件操作时遗漏了using语句?当你的应用出现内存持续增长时,是否能快速定位是托管内存还是非托管内存的问题?这些问题的答案或许就藏在你平时忽略的代码细节中。--Qwen3

.NET Memory Leaks Closure Issues Unmanaged Resources Circular Dependencies Memory Caching Issues

5 分钟 .NET 单元测试极简入门

本文通过具体代码示例介绍了使用xUnit进行单元测试的实践方法重点演示了如何针对BookService类的GetBooksByAuthor和GetBooksByPublishedYearRange方法编写测试用例文章展示了两种测试场景的编写方式正常流程验证和异常处理测试通过[Fact]属性实现基础测试用例通过[Theory]和InlineData实现参数化测试验证了null空字符串负数年份等边界条件的处理逻辑利用NSubstitute模拟对象替代真实依赖返回预设数据集并使用FluentAssertions进行断言验证测试结果包括检查返回数据数量验证属性值范围以及异常类型和消息的匹配文章提供了完整的测试代码结构包含12个测试用例覆盖了所有业务逻辑分支最后通过dotnet test命令展示了测试运行结果并附带了测试通过的截图说明测试框架能够有效验证代码逻辑的正确性和鲁棒性--Qwen3

.NET Test xunit unit testing nsubstitute tdd

借 Moq 事件谈一谈单元测试的重要性

近期.NET社区因Moq库的隐私争议引发激烈讨论其最新版本通过扫描本地git配置向Azure服务发送用户邮件地址以识别Sponsor身份这一行为在国内外产生截然不同的反响国内开发者群体对此事件关注度极低与国外社区形成鲜明对比这种反差背后暴露出国内软件开发领域长期存在的单元测试认知鸿沟作者通过代码示例揭示了Moq作为单元测试Mock工具的核心价值——通过模拟依赖接口实现代码逻辑的精准验证而非对真实数据库的直接操作单元测试的本质在于构建可信赖的代码基石它能显著提升代码质量降低维护成本并形成良性开发循环然而现实中不写单元测试的恶性循环却在持续恶化代码可维护性项目健康度和新需求开发效率都因缺乏测试保障而遭受重创当时间压力迫使开发者跳过测试时技术债务不断累积导致重构风险攀升最终陷入"开发耗时增加→交付延迟→开发加速→测试缺失"的死循环这种现状在中小型开发团队中尤为普遍开发者在缺乏测试实践的环境中逐渐丧失对代码质量的把控能力文章最后抛出值得深思的命题:为何国内开发者对单元测试的价值认知与国外存在代际差距?当技术社区对核心工具的争议反应出现断层时我们是否正在错失构建软件质量基础的关键机会?--Qwen3

.NET Test unit testing Software Development Code Quality Software Development Methodology

一幅漫画解释 .NET 垃圾收集(GC)原理

这篇博客通过一幅漫画生动解析了.NET垃圾收集(GC)机制的核心原理并借此引发对技术深度学习的思考。文章以作者在年三十发布旧文的契机揭示了国内.NET开发领域普遍存在的技术浅层化现象——许多开发者长期停留在增删改查的流水线工作中导致对底层原理的认知缺失。作者通过翻译的漫画图解展示了GC分代回收机制与大对象堆(LOH)的内存管理逻辑并指出dotnet 5新增的POH分代特性可能带来的优化空间。特别值得关注的是文中提到的LOH压缩"解决方案"通过设置GCSettings.LargeObjectHeapCompactionMode参数实现手动干预的启发式策略既暴露了GC机制的复杂性也引发对"手动内存管理是否真的可取"的反思。作者在翻译漫画时保留了原作的直观表达同时通过个人职业观察提出了技术从业者如何突破业务驱动的困境:当我们将性能优化作为突破口时是否应该重新审视基础知识的系统性学习?在GC机制不断演进的当下如何平衡自动内存管理与手动优化的边界?这些问题或许能引导开发者从机械编码转向对技术本质的探索而漫画中那些看似简单的箭头与分区是否暗示着更深层的系统设计哲学?--Qwen3

.NET dotnet garbage collection performance optimization large object heap comic translation

.NET 是如何编译的?如何阅读中间语言?

C#编译过程分为源代码转化为CIL再转化为Native code的三个阶段,其中CIL编译器负责静态编译生成包含局部变量初始化(.locals init)、栈深度声明(.maxstack)和操作码(如nop、ldarg、mul、add、stloc、ret)的中间代码,JIT编译器在运行时将CIL转换为处理器可执行的Native code。CIL通过操作码栈操作实现逻辑,如ldarg加载参数、mul/add进行算术运算、stloc存储局部变量,其中nop用于调试断点,br.s实现分支跳转。JIT编译虽带来性能开销但实现跨平台兼容,Native code难以直接阅读可通过ngen工具处理。学习IL有助于理解代码底层行为,对比操作性能差异,其中隐藏变量(如V_1)的出现与返回值拷贝机制相关,managed模式确保CLR元数据完整性,hidebysig控制方法重载隐藏逻辑。编译过程通过分层转换实现代码移植性与执行效率的平衡。--Qwen3

.NET performance optimization C# Compilation Intermediate Language JIT Compiler .NET Framework

【译】.NET SDK 将会内置容器支持,不再需要 Dockerfile

.NET 7 SDK引入了容器镜像构建功能,开发者可通过`dotnet publish`命令直接生成容器镜像,无需编写Dockerfile。该功能基于MSBuild属性实现自定义配置,支持镜像名称、版本、基础镜像等参数设置,适用于本地开发和CI管道场景。当前版本专注于Linux-x64架构,暂不支持Windows镜像和非x64架构,推送远程仓库需依赖Docker命令。核心局限包括不支持RUN命令执行系统操作、部分元数据自定义功能未实现,但计划在后续版本中完善。该功能通过简化容器构建流程(如GitHub Actions示例仅需30行配置),与传统Dockerfile相比减少了文件维护成本,未来将集成至SDK并逐步替代现有NuGet包。开发者可通过自定义基础镜像扩展功能,例如预装系统依赖,同时需关注预览阶段的已知限制,如身份验证支持待完善等问题。--Qwen3

.NET Docker .NET SDK Container Builds Linux x64 GitHub Actions

还在背依赖注入的概念?不如自己写一个依赖注入框架

文章通过构建一个简易的DI框架KDI演示了依赖注入的核心原理,重点对比了Singleton和Transient两种生命周期的行为差异。实现过程中通过Guid测试验证了Singleton在多次获取时返回相同实例,Transient则每次生成新实例。作者同时指出控制台应用中若未使用CreateScope方法,Scoped服务可能表现出与Singleton相似的特性,但通过显式创建Scope可验证Scoped实际会在不同作用域生成独立实例。最后批判了应试教育对编程学习的负面影响,强调通过实践理解技术本质的重要性,并指出Singleton服务在特定场景下可能表现出实例差异的复杂情况。--Qwen3

.NET DependencyInjection Dependency Injection Service Lifecycles Software Engineering Design Patterns

EF Core 动态构建表达式树简化 DDD 值对象的比较

文章介绍通过动态构建表达式树实现值对象相等比较的方法解决EF Core查询异常问题。用户尝试直接使用lambda表达式比较实体中的值对象属性时抛出异常,通过创建ValueObjectEqualHelper静态类的CheckEqual方法动态生成表达式树,遍历值对象属性构建二叉树结构的条件表达式。该方法处理原始类型和非原始类型属性的不同比较方式,生成的表达式能正确转换为SQL查询条件,成功解决直接比较导致的异常问题,测试结果与预期一致且生成的SQL语句正确。--Qwen3

.NET C# EF Core expression trees Entity Framework Core Dynamic Condition Generation

EF Core 动态构建表达式树为所有实体设置软删除的查询过滤器

本文探讨了在EF Core中通过动态构建表达式树实现软删除查询过滤器的自动化配置方案。针对传统硬编码方式在实体数量增加时维护成本过高的问题,作者展示了如何通过遍历实体类型、动态分析属性特征并构建Lambda表达式,实现"一处定义、全量应用"的过滤逻辑。该方案通过Expression API逐层拼接参数表达式、成员访问表达式和逻辑运算符,最终生成等效于"x => !x.SoftDelete"的查询谓词,并支持通过IgnoreQueryFilters()方法临时禁用过滤。文章不仅提供了基础实现逻辑,还展示了如何通过链式调用和语法糖优化代码可读性,揭示了C#语言特性在元编程场景中的灵活性。最后抛出值得思考的问题:当实体属性命名不统一或存在继承关系时,如何扩展该方案的适用范围?这种动态构建表达式的技术思维,是否还能应用于其他领域模型的自动化处理场景?--Qwen3

.NET EF Core lambda expressions Entity Framework Core Dynamic Expression Trees Soft Delete