C# with表达式:优雅地创建对象副本
with是C# 9.0引入的一个非常实用的特性,它让我们可以在保留原对象大部分属性的情况下,只修改少量属性并创建一个新对象。它尤其适合与record、不可变对象(Immutable Object)以及函数式编程风格结合使用。
with是C# 9.0引入的一个非常实用的特性,它让我们可以在保留原对象大部分属性的情况下,只修改少量属性并创建一个新对象。它尤其适合与record、不可变对象(Immutable Object)以及函数式编程风格结合使用。
在现代前端工程和Node.js应用开发中,文件监听是一项非常基础但又机器重要的能力。无论是:
这些功能的背后都离不开一个核心能力:如何可靠地感知文件系统的变化? Node.js原生提供了fs.watch和fs.watchFile用于监听文件变化,但它们在实际工程环境中存在大量问题:
因此,工程实践中需要一个更加稳定、统一的抽象层。chokidar正是这样的背景下诞生的。它基于Node.js原生文件监听能力,并针对不同平台进行了大量优化,为开发者提供了一套简单统一的API。本文将通过源码剖析的方式,逐步拆解chokidar的实现原理。
在现代软件系统中,应用程序越来越依赖外部资源HTTP API、微服务、数据库、消息队列、第三方服务。然而,分布式系统中失败是不可避免的。比如:网络短暂不可用、服务响应变慢、请求量突然增加、第三方API限流。如果应用程序没有任何保护机制,一个简单的异常都可能导致整个系统不可用。因此,在高可靠系统设计中,需要引入弹性(Resilience)设计模式。.NET生态中,最流行的弹性处理库就是——Polly。
WPF(Windows Presentation Foundation)自.NET Framework 3.0发布以来,一直是Windows桌面应用开发的重要技术栈。凭借XAML、数据绑定、模板化控件以及MVVM架构,WPF在企业软件、工业软件、自动化设备控制软件领域拥有大量应用。随着Windows 10、Windows 11 Fluent Design设计语言的发展,传统WPF控件逐渐显得“跟不上时代”。对于很多新项目,技术上想使用WPF的成熟生态,但是视觉体验上又希望接近Windows 11原生应用。这就是WPF UI诞生的原因之一。WPF UI是一个基于WPF的现代UI框架,它为传统WPF应用提供Fluent Design风格的控件、主题以及现代化交互体检。
在过去的学习过程中,我接触过C#、C++、Python、JavaScript等多种编程语言,也阅读和分析过一些优秀开源项目的源码。但对于Go语言,只停留在“接触过”的阶段,并没有进行过系统学习。相比于从语法、标准库、工程实践开始学习一门新语言,我更希望通过一个完整、有意思的项目进入Go的世界。因此,我选择了《用Go语言自制解释器》这本书作为Go语言学习的切入点。该书并不是一本单纯介绍Go语法的教程,而是通过实现一个完整的解释器。对于我来说,这样的学习方式非常适合。一方面,通过实现解释器,可以深入理解编程语言背后的工作机制。另一方面,在这个过程中,也可以接触Go语言的核心特性。相比单独学习Go语言,通过一个真实项目驱动学习,可以更加深刻地理解“为什么Go会这样设计”,以及这些语言特性在实际工程中的价值。因此,本文并不是《用Go语言自制解释器》的简单读书笔记,而是一次通过实现解释器深入学习Go的过程。
在传统.NET应用中,程序入口通常承担大量职责:
|
|
随着应用规模增长,Main方法会逐渐演变成创建各种对象、管理对象生命周期、初始化资源、启动后台线程、处理配置、初始化日志等等,最终形成一个巨大的入口文件。对于工业软件、桌面软件、后台服务等长期运行程序,这种方式存在明显问题:
因此,现代.NET引入了通用宿主(Generic Host)。它的核心思想:
将应用程序中的各种模块注册到Host中,由Host统一负责创建、启动、运行和关闭。
Windows桌面应用开发经历了从 Win32 API、MFC,到 Windows Forms,再到 WPF(Windows Presentation Foundation)的演进。相比传统桌面开发技术,WPF 不仅仅是一个新的 UI 框架,更是一套重新定义桌面应用开发方式的技术体系。它将界面描述、数据绑定、图形渲染、动画效果、样式模板以及应用逻辑进行了更清晰的分离,使开发者能够构建更加现代化、可维护、可扩展的桌面应用程序。
作为一名从事 C#/.NET 开发的工程师,WPF 一直是 .NET 桌面开发体系中不可绕过的重要技术。虽然近年来 Web、移动端以及跨平台技术快速发展,但在工业软件、自动化设备上位机、生产管理系统、视觉检测软件等领域,基于 WPF 的桌面应用仍然具有非常广泛的应用场景。尤其是在工业自动化领域,设备控制软件通常需要复杂的交互界面、实时数据展示、丰富的图形化配置以及良好的工程扩展能力,而 WPF 凭借其强大的 UI 描述能力和 MVVM 架构模式,依然是构建此类应用的重要选择。
《WPF编程宝典:使用C# 2012和.NET 4.5(第4版)》是 WPF 领域非常经典的学习资料之一。本书由浅入深地介绍了 WPF 的核心概念,包括 XAML、布局系统、控件体系、依赖属性、路由事件、数据绑定、资源、样式、模板、动画、图形绘制发等内容。相比简单介绍 API 的书籍,本书更注重帮助开发者理解 WPF 背后的设计思想,以及如何利用 WPF 构建真正工程化的软件系统。
在普通人的认知中,电机通电->电机旋转->设备运动,似乎只需要一个电机就能完成机械运动。但在工业化设备中,例如:半导体检测设备、手机组装设备、MTF光学检测设备、精密点胶设备、贴片机、激光加工设备等。设备要求的不是“运动”,而是移动到指定位置误差小于几个微米、速度稳定、加减速平滑、多轴协同、高重复定位精度、实时响应外部触发等等。例如:
一个视觉检测设备,需要相机移动到指定位置拍照,如果运动误差超过5μm,视觉算法得到的结果可能完全失效。
这时候,仅靠电机无法满足需求。工业设备需要一套完整的运动控制系统(Motion Control System),其中核心的组成就是:
人工智能的发展正在经历一次深刻的范式转变。过去十年,机器学习的核心目标更多集中在训练一个能够完成特定任务的模型:给模型大量数据,通过优化算法调整参数,让模型学会分类、预测、生成文本或理解图像。然而,以 ChatGPT 为代表的大语言模型(Large Language Model, LLM)的出现,让 AI 的角色发生了变化:
AI 不再只是一个被动响应问题的模型,而正在逐渐成为能够规划、调用工具、持续学习并完成复杂任务的智能体(Agent)。
在这个快速演进的时代,我们不仅需要理解“如何使用模型”,更需要深入理解:
这些问题,正是李宏毅老师《Machine Learning 2026 Spring》课程试图探索的方向。本课程不再局限于传统机器学习中的监督学习、优化算法或模型训练流程,而是聚焦当前人工智能领域最前沿的问题:
希望通过这系列学习笔记,不只是记录课程内容,更希望从工程实践和系统设计的角度,理解现代 AI 系统背后的技术原理。
在C#的发展过程中,有一个非常重要的转折点,那便是从「如何操作数据」转向「描述想要什么数据」。在LINQ出现之前,我们通常需要通过循环、条件判断、临时变量等方式完成数据查询。例如:
|
|
而LINQ提供了一种完全不同的思考方式:
|
|
我们不再关注如何遍历集合,而关于我需要哪些数据,这就是LINQ带来的核心变化:从命令式编程(Imperative Programming)转向声明式编程(Declarative Programming),本文将记录了学习LINQ的过程。
最近开始阅读LevelDB源码,希望通过源码理解一个优秀 C++ 项目的工程设计。当我打开LevelDB项目目录时,发现CMakeLists.txt几乎贯穿整个项目,但是我之前并没有怎么使用过CMake。CMakeLists.txt的内容让我有点无法理解。于是产生了几个问题:
带着这些问题,开始学习CMake。
学习一门语言最有效的方式或许并不是从语法手册开始,而是通过一个真实项目理解语言的奥秘。因此,我选择了rustnet作为Rust学习的入口。rustnet是一个基于Rust实现的网络监控工具,它涉及网络连接管理、数据包捕获、协议解析、异步处理,包含了大量Rust在系统编程中的典型应用场景。因此,这次源码剖析不仅仅是为了理解rustnet的实现细节,更重要的是希望通过这个项目逐渐建立Rust的使用方法和工程思维。本文将会采用问题驱动的方式,从程序入口开始,逐步探索项目架构、核心模块、关键技术实现,逐步理解Rust设计背后的理念。希望通过这次源码阅读之旅,能够从一个Rust小白的视角,逐渐掌握Rust的核心思想,并最终具备阅读和参与大型Rust项目的能力。
在日常开发启动后端服务时,经常会遇到类似EADDRINUSE: address already in use :::3000的问题。这类问题的本质是:
某个进程已经占用了目标端口,需要找到该进程并进行处理。
本文介绍如何使用PowerShell(pwsh)快速根据端口查找对应进程,并进一步查看、停止进程。
很多时候,我们学习了一个前端框架,更多停留在API使用层面:知道如何创建组件、如何调用生命周期、如何进行状态管理,却很少去思考一个真实的大型项目是如何组织代码、如何设计组件体系、如何管理复杂业务逻辑,以及如何将Vue的能力真正应用到工程实践中。因此,我选择了douyin作为学习对象。该项目基于Vue技术栈实现了一个仿抖音Web应用,在Github上已收获了11.5k Star。相比简单的Demo项目,它更加接近真实业务场景,设计页面架构设计、组件拆分、状态管理、接口交互、性能优化以及前端工程化等多个方面。
通过对该项目源码的阅读与分析,我希望不仅仅了解“Vue怎么用”,更进一步探索:
这篇源码剖析文章并不是简单介绍项目如何运行,而是希望站在学习者的角度,通过阅读源码逐步回答这些问题,从项目整体架构开始,深入到关键模块实现,理解一个Vue项目背后的设计思想。于我而言,这也是一次从“Vue使用者”向“Vue工程实践”的美妙之旅,希望通过分析这个项目,建立对现代前端项目架构和工程化实践更加系统的认识。
设计模式(Design Patterns) 是软件工程中用于解决特定设计问题的经典方案,也是面向对象设计能力的重要体现。然而,很多开发者在学习设计模式时,往往停留在「记住二十三种模式」的层面,却很难理解为什么需要某种模式、它解决了什么问题,以及在现代 .NET 项目中应该如何使用。为了更系统地掌握设计模式,我选择学习Dmitri Nesteruk的在线课程Design Patterns in C# and .NET。该课程并非简单介绍GoF(Gang of Four)的 23 种设计模式,而是从设计原则出发,结合大量 C# 示例,深入讲解各种模式的设计思想、适用场景、优缺点以及不同模式之间的联系,并讨论现代 C# 语言特性对传统设计模式的影响。
本篇文章将作为我的课程学习笔记,也是对整个课程内容的一次系统梳理。文章不会局限于对每个模式的定义进行罗列,而是围绕以下几个问题展开:
希望通过这篇文章,不仅能够完整记录自己的学习过程,也能够帮助读者从设计思想而非模式名称的角度理解设计模式,在实际项目中真正做到根据问题选择设计,而不是为了使用模式而使用模式。
MongoDB 是当前最流行的 NoSQL 数据库之一,它采用文档模型存储数据,通过灵活的数据结构、高性能的索引机制以及完善的分布式能力,广泛应用于互联网应用、大数据处理和实时业务场景。但想真正理解 MongoDB,仅仅掌握 CRUD 操作和查询语法是不够的。MongoDB 背后涉及许多数据库核心概念:文档模型设计、BSON存储、索引原理、WiredTiger存储引擎、MVCC并发控制、副本集以及分片架构等。本文将结合《MongoDB权威指南》,从使用实践逐步深入底层原理,探索 MongoDB 的设计思想以及它如何解决现代应用中的数据存储和扩展问题。