8.4:今日概念与语法总结

今日概念与语法总结

日期:2026-08-04


一、语法点

语法 一句话
public class X : IDisposable 公开类 + 承诺提供资源释放方法
构造函数 跟类同名、无返回值类型,new 时自动调用
I 开头类型 接口,只定义方法签名不实现
依赖注入 不自造对象,等外面传现成的
IOptionsMonitor<T> 实时配置监听,文件改了就感知
ILoggerFactory 工厂,能按需造出不同标签的日志记录器
ILogger<T> 泛型参数自动取类名作日志标签
CancellationTokenSource 类类型,既能主动发出取消,也能读令牌
CancellationToken 值类型结构体,只能被动检查状态
CreateLinkedTokenSource 把多个令牌串成 OR 逻辑
null! null 宽容操作符,赋空值同时抑制编译器警告

二、重要概念具体说明

2.1 依赖注入

是什么 :构造函数不自己 new 对象,而是要求外面传一个现成的进来。

csharp 复制代码
// ❌ 硬编码------把自己和具体实现焊死了
class Worker {
    private ITool _tool;
    public Worker() {
        _tool = new Hammer();  // 只能用锤子,换不了
    }
}

// ✅ 依赖注入------外面给什么用什么
class Worker {
    private ITool _tool;
    public Worker(ITool tool) {
        _tool = tool;  // 传锤子用锤子,传扳手用扳手
    }
}

好处:换实现只改外面注入,Worker 一行不动。

类比:不自己进厨房炒菜,服务员端上来什么吃什么。换厨师不用换盘子。

2.2 接口 vs 实现

是什么:参数类型写接口(壳),实际传进来的是具体类对象(肉)。

csharp 复制代码
// 接口:只定义方法签名
interface ITool {
    void Use();
    void Stop();
}

// 实现:具体干活
class Hammer : ITool {
    public void Use() { /* 砸 */ }
    public void Stop() { /* 停 */ }
}

// Worker 只认接口,不关心底层是 Hammer 还是 Wrench
class Worker {
    public Worker(ITool tool) { ... }
}

类比:插座(接口)形状标准化,插什么电器(实现)都行。灯、风扇、充电器------只要插头符合规格。

2.3 IOptionsMonitor(实时配置)

是什么:配置文件在磁盘上改了,立即感知到。

对比:

csharp 复制代码
// IOptions ------ 死的,启动时拍快照
class Worker {
    public Worker(IOptions<Config> cfg) {
        var v = cfg.Value.Voltage;  // 永远是启动时的值
    }
}

// IOptionsMonitor ------ 活的,文件改了就感知
class Worker {
    public Worker(IOptionsMonitor<Config> cfg) {
        var v = cfg.CurrentValue.Voltage;  // 每次读都是最新的
    }
}

底层:开了文件监听器。磁盘变动 → 系统通知 → 重新加载。

Microsoft 在配置扩展包里定义了三种:启动读一次不更新、每次请求读一次、实时监听。这是框架写死的。

2.4 工厂模式(ILoggerFactory)

是什么:不传成品,传"能造成品的机器"。

csharp 复制代码
// ❌ 直接传成品------只能固定用一种日志记录器
class Worker {
    public Worker(ILogger logger) {
        logger.Log("Worker 的消息");  // 只能打一种标签
    }
}

// ✅ 传工厂------内部按需造不同标签的日志记录器
class Worker {
    private ILogger _logger;
    private ILogger _subLogger;

    public Worker(ILoggerFactory factory) {
        _logger    = factory.CreateLogger("Worker");    // 主标签
        _subLogger = factory.CreateLogger("SubModule");  // 子模块标签
    }
}

为什么用泛型 CreateLogger<T>:自动取类名当标签,不用手写字符串。

类比:自动售货机------说"可乐"吐可乐,说"雪碧"吐雪碧。你不用知道怎么造的。

2.5 日志五级别

csharp 复制代码
logger.LogTrace("最细跟踪");
logger.LogDebug("调试信息");
logger.LogInformation("正常记录");   // 日常最常用
logger.LogWarning("警告但还能跑");
logger.LogError("出错了");          // 必须处理

实际输出受配置控制------设定只显示 Warning 以上,Info 及以下就不输出。

2.6 统一接口 + 可换底层

微软定接口,各家实现,业务代码只认接口。

复制代码
业务代码 → ILogger 接口(统一层)
              ↓
         Serilog / NLog / Console(底层,注入时指定)

换底层:注入时切一行,业务代码不感知。本项目底层是 Serilog------按天切割文件,不同模块独立日志。

2.7 取消令牌三层设计

背景:任务需要响应两种取消来源------外部停止按钮 + 内部异常自主停止。同时要把"谁有权喊停"和"谁只能感受"分开。

csharp 复制代码
class Worker {
    private CancellationTokenSource _selfCts;    // 内部喊停源
    private CancellationTokenSource _linkedCts;   // 合并后的源
    public  CancellationToken       CancelToken;  // 只读输出

    public Worker(CancellationToken externalToken) {
        // 第一层:自己创建一个独立的取消源
        _selfCts = new CancellationTokenSource();

        // 第二层:把自己 + 外部 串成 OR
        _linkedCts = CancellationTokenSource.CreateLinkedTokenSource(
            externalToken,      // 外部(停止按钮)
            _selfCts.Token      // 内部(异常自主停止)
        );

        // 第三层:只输出只读令牌,不给 Cancel 权力
        CancelToken = _linkedCts.Token;
    }

    void OnError() {
        _selfCts.Cancel();  // 内部异常时自己喊停
    }

    void DoWork() {
        while (!CancelToken.IsCancellationRequested) {
            // 干活...任一源头取消就自动跳出
        }
    }
}

串联逻辑CreateLinkedTokenSource(A, B) = A 或 B 任意取消,合并后的就取消。就像串联电路两个开关------谁拉闸都断电。

为何三层

能力
_selfCts 内部主动 Cancel
_linkedCts 内外 OR,也能 Cancel
CancelToken 只读,只能检查 IsCancellationRequested,不能 Cancel

_linkedCtsCancel() 留在手里,只把 .Token(只读副本)放出去------防止其他代码误操作把任务停了。

类比 :遥控器只有你有(_linkedCts),别人只能看屏幕亮了没(CancelToken),不能换台。

2.8 CancellationTokenSource vs CancellationToken

csharp 复制代码
// CancellationTokenSource ------ 能主动喊停的完整源
var source = new CancellationTokenSource();
source.Cancel();                           // ✅ 主动喊停
bool stopped = source.Token.IsCancellationRequested;  // ✅ 也能检查状态

// CancellationToken ------ 只能被动检查,没有 Cancel 方法
CancellationToken token = source.Token;
// token.Cancel();                         // ❌ 编译错误!没这个方法
bool stopped = token.IsCancellationRequested;  // ✅ 只有这一个能力
CancellationTokenSource CancellationToken
类型 类(引用类型) 结构体(值类型)
能 Cancel?
能查状态?
谁用 控制端 检测端

2.9 null! 操作符

C# 8.0 引入。

csharp 复制代码
// ❌ 不加 ! ------ 编译器黄线警告:非空类型不该为 null
WorkerInfo info = null;

// ✅ 加 ! ------ 告诉编译器:闭嘴,后面一定赋值
WorkerInfo info = null!;

什么时候用:声明时暂赋空值,后面的 if 分支里才真正赋值。

本质:不是语法需要,是压制编译器警告。

2.10 基础设施 vs 业务数据

csharp 复制代码
class Worker {
    public Worker(
        ITool tool,           // 基础设施:换任务不变
        ILogger log,          // 基础设施
        CancellationToken tok,// 基础设施
        TaskData data         // 业务数据:换任务全变
    ) { ... }
}
类别 包含什么 换任务后
基础设施 硬件、日志、配置、取消信号 不变
业务数据 任务目标、任务参数 全变

类比:厨房(基础设施=锅碗灶台)vs 菜单(业务=今天吃什么)。


三、AI 规则(元认知)

每条规则堵同一个洞:"看到输入→自动填空→直接输出"。

核心:所有任务的第一句话只能是确认复述,不准其他任何内容。

  1. 只说确认,等点头
  2. 一次一个点
  3. 讲完停
  4. 简洁
  5. 多个概念拆开
  6. 记录文件为唯一规则来源
  7. 每段结尾必带问句
  8. 只想当前,憋回去
  9. 每行必讲不跳过
相关推荐
大数据张老师1 小时前
Typora 导出 Word 模版操作手册
开发语言·c#·word·typora
我是苏苏2 小时前
C#基础:使用System.Speech.Synthesis离线播放/朗读文字内容
开发语言·c#
程序员-Benothing4 小时前
如何实现高并发系统订单30分钟自动关闭?
开发语言·c#·wpf
海盗123416 小时前
微软技术周报 ——2026-08-03
后端·python·microsoft·c#·.netcore
dalong101 天前
WPF:3D甜甜圈
3d·c#·wpf·甜甜圈
神秘的MT1 天前
C# WinForm Socket 类 常用方法 (C# .NET,TCP 场景)
服务器·网络·学习·tcp/ip·c#·winform
神罚天下ET2 天前
c# ACME client (补充)
开发语言·c#
噗噗夹的TA之旅2 天前
Shader 学习 21:自定义 Render Feature
学习·游戏·unity·c#·游戏引擎·图形渲染
脚踏实地皮皮晨2 天前
003006001_WrapPanel控件
开发语言·c#·.net·wpf·visual studio