news 2026/10/22 7:12:09

注释:写给人看的说明(零基础入门 · 第 4 篇)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
注释:写给人看的说明(零基础入门 · 第 4 篇)

摘要:C# 注释怎么写?这篇讲清单行注释、块注释、XML 文档注释三种写法,每种都能直接复制运行。动手验证注释不能嵌套会报 CS1525、双引号里的注释符号不会被解析、文档注释贴错位置编译器也不拦你,再实测开启文档生成后触发 CS1591 警告的全过程。哪些注释该写、哪些写了等于没写,批量注释快捷键怎么用,一次说透。零基础入门 · 第 4 篇。

难度:★☆☆☆☆ 预计阅读 10 分钟

上一篇我们把 Program.cs 里那 12 行拆了个干净。收尾时你大概已经发现一个问题:每一行代码都清清楚楚地说了"做了什么",但没有一行说"为什么这么做"。

三个月后你回来改这段代码,Console.WriteLine 还能看懂,可当初为什么在这儿多判一个条件、那个魔数 3600 是哪来的,翻遍整个文件也找不到答案。注释就是为这件事准备的。

这篇目标很具体:你能判断一段代码该不该加注释、该加哪种、以及怎么让 Visual Studio 帮你写。


一、三种注释,先认个脸

C# 的注释一共三种,长得完全不一样:

写法 名字 范围 编译器看它吗
// 单行注释 到这一行结尾为止 完全无视
/* */ 块注释 中间夹住的所有内容 完全无视
/// XML 文档注释 三斜杠,贴成员 会读,但只用来生成文档

前两种是纯粹给人看的,写多写少都不影响程序跑。第三种不一样——编译器会去读它,用它生成一份 XML 文档文件,某些设置下还会因为它报警告。这条后面单独讲。

现在打开你的 Program.cs,把里面全部内容删掉,原样敲下面这段:

using System; namespace HelloWorld; class Program { static void Main(string[] args) { // 这是一行单行注释,打印一句话 Console.WriteLine("第一行"); /* 这是一段块注释 可以横跨好几行 里面想写几行写几行 */ Console.WriteLine("第二行"); } }

F5,输出:

第一行 第二行

三条注释一个都没出现在输出里,程序也跑得好好的。这就是注释的全部含义:写给人看的东西,编译器直接跳过。

顺便验证一下编译器有多"无视":把上面那个 Console.WriteLine(“第一行”); 整行前面加上 //,再 F5。它不会执行了,输出只剩一行 第二行。

再次 F5 之前记得把那两斜杠删掉。 留着注释掉一行代码到处跑,是新手最容易攒下的一堆坑。


二、// —— 前面带一行,后面带一句

// 的规则只有一条:从这两个斜杠开始,到这一行结尾为止,全是注释。

它有两种摆法。

摆法一:写在代码上一行。 这是主力用法,用来解释接下来这段代码在干什么。

// 把用户输入的名字原样打印出来,不做任何加工 Console.WriteLine(name);

摆法二:写在代码后面。 只在补一句很短的话时用。

Console.WriteLine("第一行"); // 用换行结尾,下一句才能对齐 Console.WriteLine("第二行");

摆法二别连着用。 连续三行都挂尾注,代码会横向拖得很长,很难读:

int a = 1; // 初始化 a int b = 2; // 初始化 b int c = 3; // 初始化 c 这个注释纯属废话因为谁都能看出来

上面第三行那个注释就是典型的废话注释,第三篇说过:代码已经说清楚的事,注释就别再说一遍。判断标准很简单——删掉这行注释,读代码的人会不会卡住?不会,就删掉。

为什么 // 不能跨行

因为它的范围被"行尾"卡死了。C# 编译器扫代码时遇到换行符就知道这条注释结束了。

有个例外要记住:字符串里不算行尾。 下一节专门讲这个。


三、/* */ —— 一次盖好几行

/* 开始,*/ 结束,中间夹多少行都算注释。

它存在的理由只有一个:// 一次只能注释一行,而块注释可以一口气盖掉一整段。

/* 下面这三种算法各有各的适用范围: 1. 冒泡排序:实现简单,适合几十条的小数据量 2. 快速排序:平均最快,需要递归 3. 归并排序:最稳定,但要额外开一块内存 暂时都不需要,先留着备查 */

// 也能写这么长,只要每行前面都补一个 //:

// 下面这三种算法各有各的适用范围: // 1. 冒泡排序:实现简单,适合几十条的小数据量 // 2. 快速排序:平均最快,需要递归 // 3. 归并排序:最稳定,但要额外开一块内存 // 暂时都不需要,先留着备查

这两种写法效果完全一样。 那为什么还要 /* */?有个实际原因——给代码临时注释掉的时候,// 更安全,下一节就讲为什么。

一个纯排版习惯

块注释每行前面习惯性加一个 *:

/* * 这是一个块注释 * 这是第二行 */

开头那个 /* 后面不加 *,这是行规不是语法。编译器只认 */ 两个字符收尾,加不加 * 它都不管。这样写纯粹为了对齐好看、扫一眼就知道是注释的开始。你要是不加,也不算错。


四、关键实验:块注释不能嵌套

这条是本文最容易被网上文章讲错的地方,所以你自己跑一遍。

你可能听过这么一句话:“块注释里可以再写块注释,就像 C++ 那样。” 在 C# 里这是错的。

官方语言规范里写得很明确:“Comments do not nest.”(注释不嵌套。)

现在动手试。打开 Program.cs,全部删掉,敲这段——就是故意写错:

using System; namespace HelloWorld; class Program { static void Main(string[] args) { /* 外层块注释开始 /* 内层块注释试图嵌套 */ Console.WriteLine("这行在嵌套注释里吗?"); */ Console.WriteLine("A"); } }

F5,红字来了:

Program.cs(12,10): error CS1525: 表达式项“/”无效

编译器到底干了什么

它根本没去区分"内层"和"外层"。它的做法简单到近乎粗暴:遇到第一个 */ 就认定注释结束。

所以这段代码实际是这样解析的:

行 编译器怎么理解
/* 外层块注释开始 注释开始
/* 内层块注释试图嵌套 */ 还在注释里。这行的 */ 把注释关掉了
Console.WriteLine(“这行在嵌套注释里吗?”); 注释已经关了,这是真正的代码
*/ 代码里冒出个没头没尾的 */,报错

注意第 3 行——你以为它在注释里,其实它是一句货真价实的可执行语句,只不过那句 Console.WriteLine 真的被执行了。

报错位置报在第 12 行那个孤零零的 */,也就是注释提前关闭之后编译器第一个撞上"不该出现的字符"的地方。真正的问题在第 10 行。

那要怎么注释一大段代码

用 // 一行一行加,别用 /* */ 包起来。也可以用 VS 的快捷键——第四节末尾会说。

记住这条规则的用处在于:以后看到 CS1525 且报错行里有个 */,不用怀疑自己,直接去找上面有没有一个块注释被提前关掉了。


五、双引号里的 // 不是注释

这条听起来像废话,但它解释了为什么"注释掉一大段代码"用 // 比用 /* */ 安全。

编译器在字符串里的行为:不解析注释。 双引号包起来的内容,一个字符都不当语法看。

打开 Program.cs,全部替换成这段:

using System; namespace HelloWorld; class Program { static void Main(string[] args) { // 双引号里的 // 不是注释 Console.WriteLine("这里有个 // 符号"); // 双引号里的 /* 也不是注释 Console.WriteLine("这里有个 /* 符号"); // 双引号里的 */ 同样不是注释 Console.WriteLine("这里有个 */ 符号"); } }

F5,输出:

这里有个 // 符号 这里有个 /* 符号 这里有个 */ 符号

三个符号全打印出来了,一个都没让编译器出错。

这解释了一件事

假设你有一段代码,里面正好有一行字符串带 */:

string endMark = "*/";

你嫌它暂时用不上,想整段注释掉,于是手一抖:

/* 暂时不用这段 string endMark = "*/"; Console.WriteLine(endMark); */

结果就是你上一节看到的 CS1525——注释在字符串里那个/ 处提前关闭了。问题不在 // 和 /上,在 */ 上。 而用 // 逐行注释,根本不会碰到这个坑。


六、/// —— 唯一一种编译器会读的注释

前两种注释编译器完全无视。第三种不一样。

术语解释:XML 文档注释(XML documentation comment)指用三个斜杠 /// 开头、写在类、方法等成员正上方的一段说明。它的内容按 XML 格式书写,编译器会去读它,然后生成一份 .xml 文档文件。

写法长这样:

using System; namespace HelloWorld; /// <summary> /// 一个用来演示的程序。 /// </summary> class Program { /// <summary> /// 程序从这里开始执行。 /// </summary> static void Main(string[] args) { Console.WriteLine("A"); } }
是标签,< 和 > 是标签的括号——这套写法来自 XML,一种用尖括号标记结构的纯文本格式。整个 C# 的注释体系里,这是唯一一处 // 和 /* 之外的语法味道。

必须紧贴成员,中间不能有空行。 上面 /// … 和 class Program 之间只有换行、没有空行,这个 summary 才会算作 Program 的说明。中间插入一个空行,它就成了"悬空的注释",编译器读不到归属。

标签没写对会怎样

少写一个 <、 忘了闭合,都属于 XML 结构错误,会报:
warning CS1570: XML 注释格式不正确

让 Visual Studio 帮你写

不用背。光标放在要写说明的成员上,按 Ctrl+Shift+C(菜单路径:编辑 → 高级 → 添加 XML 文档注释),VS 自动插好骨架并把光标放进 和 中间,直接打字就行。

你也可以手动敲三个斜杠,VS 同样会自动补全标签。

一个重要实验:为什么你的控制台项目没报警告

很多教程说"写了 /// 却收到警告 CS1591",但你现在的项目加了两行 ///,构建面板干干净净:

0 个警告 0 个错误

这不是你写对了,是你的项目压根没让编译器去管这件事。

想亲眼看到 CS1591,照着做:

  1. 在解决方案资源管理器里右键项目名 → 属性
  2. 顶部的下拉框从 活动配置 切到 所有配置
  3. 找到 生成 → 输出 那一栏
  4. 勾上 生成包含 API 注释的文件(英文项目里是 Generate XML documentation file)

等价的做法是直接在 .csproj 里加一行:

<PropertyGroup> <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup>

注意:类名默认不写修饰符就是 internal(程序集内可见),不叫"公开可见"。 官方文档明确说 CS1591 只针对公开可见的类型和成员。所以光开这个勾选项还不会报。

再把 Program 前面补一个 public:

using System; namespace HelloWorld; public class Program { public static void Main(string[] args) { Console.WriteLine("A"); } }

现在 F5(或者 Ctrl+Shift+B 只编译),警告列表里出现:

warning CS1591: 缺少对公共可见类型或成员“Program”的 XML 注释 warning CS1591: 缺少对公共可见类型或成员“Program.Main(string[])”的 XML 注释

最后 bin\Debug\net10.0\ 目录下会多出一个 t1.xml(跟你项目名同名的那个)。打开它,里面就是编译器把你的 /// 转成的结构化文档:

<?xml version="1.0"?> <doc> <assembly> <name>t1</name> </assembly> <members> </members> </doc>

members 是空的,因为你把 /// 删掉了。这就是 /// 的真正去处——它不是写给编辑器看的,是写给文档生成工具看的。

那要不要开这个设置

控制台项目、练手项目:不用开,也没必要开。 你是在学语法,不是在发布类库。

写给别人用的类库、需要生成 API 文档的项目:开,而且应该把每个公开成员都补上。 这是 .NET 生态里的行业惯例,官方文档管这叫"XML 注释"。

CS1591 只是警告,不是错误——程序照样能跑,不会拦住你。 这一点新手常搞混。

补一个反直觉的实验

有篇流传很广的说法是"文档注释贴错位置会报 CS1587"。在现在的编译器上不成立。

把 /// 贴在一个语句正前方,而不是成员上:

using System; namespace HelloWorld; class Program { static void Main(string[] args) { /// <summary> /// 这个文档注释贴错了位置,它紧贴的是一个语句。 /// </summary> Console.WriteLine("A"); } }

编译结果:0 个警告,0 个错误。

编译器只是默默忽略了它。所以你把注释贴歪了,程序不会拦你——它也不会生效,那段说明不会出现在任何文档里。 靠编译器提醒是等不到的,只能自己检查。


七、VS 的注释快捷键

手敲 // 慢,尤其是给选中的一堆行批量加注释。四个快捷键解决:

快捷键 官方名称 干什么
Ctrl + / 切换行注释 选中的每一行前面加 //,已经有了就去掉
Ctrl + Shift + / 切换块注释 整段包上 /* */ 或拆掉
Ctrl + Shift + C 添加 XML 文档注释 生成 /// 骨架
Ctrl + K 再按 Ctrl + C 批注选择 老版本的注释方式,还能用

菜单路径都在 编辑 → 高级 下面。(上面第 4 节键位是 VS 2022 引入的,你用的是 VS 2026,直接支持。)

Ctrl + / 是最该记住的一个。 试一下:

  1. 选中 Main 方法里那四行
  2. 按 Ctrl + /

VS 给每一行前面都补上了 //,代码立刻变灰。再按一次,全部恢复原状。

它默认用 // 而不是 /* */,正是第四节那个实验的直接原因——逐行加注释不会遇到嵌套和提前闭合的坑。你手动用块注释包一大段代码之前,先想想里面有没有 */。

顺手提一个坑:这个快捷键在中文输入法下经常失灵,敲出来是个问号。原因是 Ctrl + / 和输入法切换快捷键撞了。解决:换成英文输入法再按;或者用 编辑 → 高级 → 切换行注释 点菜单,效果一样。


八、常见错误汇总

CS1525:表达式项“/”无效

你看到行尾有个孤零零的/,十有八九是被注释掉了。往上翻,找一个 /是不是在它之前就被别的 */ 提前关掉了。成因基本只有两个:块注释里嵌了块注释,或者被注释的代码里有一行字符串带 */。

注释贴歪了没任何提示

刚才那个实验证明了——/// 贴到语句前面,编译器一声不吭。这不是 bug,文档注释本来就只对成员生效。靠看代码检查,不靠等报错。

CS1591:缺少对公共可见类型或成员"xxx"的 XML 注释

只在你主动开了"生成包含 API 注释的文件"之后才可能出现,而且只针对 public / protected 的成员。三个办法:补上 ///、把成员改成 internal、或者干脆关掉那个勾选项。练手项目关掉最省事。

警告和错误不是一回事

CSxxxx 后面带 error 的是错误,编译直接失败,程序跑不起来。带 warning 的是警告,照常生成照常跑。新手看见"1 个警告"就慌,大可不必——只有错误才拦路。

打开 .csproj 时看到一堆看不懂的标签

第一节改设置需要动这个文件,文件里全是 、 之类的标签。别整段重写,只照着格式加一行 true,加错了会看到 CS5001 或者一堆 XML 解析报错。


练习题

三题都在 Program.cs 上动手。第 2、3 题建议先写下来再动手。

第 1 题

下面这段代码,F5 之后控制台上会打印几行?请写出每一行的内容,并说明原因:

using System; namespace HelloWorld; class Program { static void Main(string[] args) { Console.WriteLine("1"); /* 输出 1 */ /* Console.WriteLine("2"); */ Console.WriteLine("3"); // 输出 3 // Console.WriteLine("4"); /* Console.WriteLine("5"); Console.WriteLine("6"); */ } }

第 2 题

下面这段代码你猜会报什么错?先写下来,再动手敲验证,看看和你猜的差多少:

using System; namespace HelloWorld; class Program { static void Main(string[] args) { /* 第一段注释 /* 第二段注释 */ int a = 1; */ Console.WriteLine(a); } }

请回答:

(a)完整的报错编号和中文描述是什么?

(b)报错报在第几行?真正出问题的是第几行?

(c)int a = 1; 这一行,它会执行吗?为什么?

(d)把这四行注释写法改成一种能正常编译的写法。

第 3 题

下面是一段带注释的代码。请挑出至少三处不该写的注释,说明每处为什么多余,然后给出你改完之后的版本:

using System; namespace HelloWorld; class Program { static void Main(string[] args) { // 声明变量 int total = 0; // 循环 for (int i = 1; i <= 100; i++) { // 把 i 加到 total 上 total = total + i; } /* 输出结果 */ Console.WriteLine(total); } }

参考答案

第 1 题

打印 两行,内容是 1 和 3。

逐行过一遍:

代码 执行吗 为什么
Console.WriteLine(“1”); 是 后面挂的 /* 输出 1/ 是块注释,只盖住自己那段
/
Console.WriteLine(“2”); */ 否 整行在注释里
Console.WriteLine(“3”); 是 后面挂的 // 输出 3 同样只是备注
// Console.WriteLine(“4”); 否 整行在注释里
那两行 Console.WriteLine(“5”) / (“6”) 第五行否、第六行否 看起来像"注释掉了两行",但编译器不这么读

最后那两行是这道题的全部考点。编译器遇到第一行的 /* 开始注释,一路读到第二行的 */ 才结束。所以:

  • Console.WriteLine(“5”); 在注释里 → 不执行
  • Console.WriteLine(“6”); 在注释里 → 不执行
  • 结尾那个/ 后面紧跟的是 }(类的闭合大括号)——注意这里没报错,纯属运气好。因为注释从 /到 */ 正好覆盖了两行,结尾的 */ 被消耗掉了,后面剩下的是完好的代码。

如果那两行再多写一句代码,末尾的/ 就会露出来,你会看到 CS1525。所以"这段看起来被注释了"不等于"这段真的被注释了",得数一下 /和 */ 的个数。

第 2 题

(a) 完整报错:

Program.cs(12,10): error CS1525: 表达式项“/”无效

CS1525 的中文描述就是"表达式项“/”无效"。猜测不中很正常,编号本身不重要,重要的是它属于"多出来一个 / 符号"这一类,看到这个就该往注释方向找。

(b) 报错在第 12 行(那个孤零零的/),真正出问题的是第 10 行那个试图嵌套的内层 /。

编译器不做"嵌套"判断,它只认第一个 */。第 10 行末尾的 */ 把注释关掉了,第 11 行 int a = 1; 就成了正常代码,第 12 行的 */ 成了没人认领的符号。

(c) 会执行。 这是这道题最反直觉的地方。

int a = 1; 位于第 11 行,正好在"第 10 行注释关闭"之后、"第 12 行报错"之前。编译器把它当成一句普通的、完好的赋值语句处理了。

想亲眼验证的话,把第 12 行那个多余的 */ 删掉,只留前 11 行,F5,控制台会打印出 1。

/* 第一段注释 /* 第二段注释 */ int a = 1; Console.WriteLine(a); // ← 输出 1

(如果编译器连 int a = 1; 也一起忽略,那报错就不会出现在第 12 行了。)

(d) 两种改法都能编译:

用 // 逐行注释(推荐):

// 第一段注释 // 第二段注释 // int a = 1; Console.WriteLine(3);

或者干脆把内层那对标记去掉,让外层注释包住全部:

/* 第一段注释 第二段注释 int a = 1; */ Console.WriteLine(3);

第一种是日常写法。 第四节说过原因:逐行加 // 天然避开了 */ 提前闭合的问题。

第 3 题

三处不该写的注释:

注释 为什么多余
// 声明变量 int total = 0; 一眼就知道是声明并初始化。看不懂的人不是新手,是压根不该看这段代码
// 循环 for 关键字本身就是循环的说明书。写 // 循环 相当于给门牌上写"这是一扇门"
// 把 i 加到 total 上 这条最典型。total = total + i; 的意思用眼睛读一遍就懂,注释一个字的额外信息都没提供

另外 /* 输出结果 */ 也算半个废话——它没说出任何代码之外的东西,属于"复述"而不是"解释"。

判断标准给一条:注释应该提供代码本身给不了的信息。 凡是把代码翻译成中文念一遍的,删掉;凡是解释"为什么这么写"“这里为什么特殊”“这个数哪来的”,留下。

改完的版本:

using System; namespace HelloWorld; class Program { static void Main(string[] args) { int total = 0; for (int i = 1; i <= 100; i++) { // 从 1 加到 100 而不是从 0 开始:第 0 轮等于什么都没加,白跑一次 total = total + i; } Console.WriteLine(total); } }

现在只留了一条注释,它回答了代码回答不了的问题——为什么从 1 开始而不是 0。这条删掉之后,后来的人真的会去猜。

如果 total 那两行再配一条说明"这里没用 += 是为了照顾还没学到运算符的读者",那就属于过度注释了。同一份代码,同一个人,注释密度应该跟着读者的水平走。


下一步

下一篇:《变量:给内存里的数据起个名字》

今天这十几行代码里,你已经能写出注释了。但有一个问题还没解决:Console.WriteLine(“A”); 里面那个 “A” 是死的,写什么就打印什么。如果你想打印用户输入的名字,那个名字从哪来、怎么先存起来再打印?

下一篇讲变量。int age = 18; 这一行会拆成四部分讲清楚——类型是什么、名字是什么、= 右边是什么、存进去之后这个 age 到底意味着什么。学完你能写出第一个能接收输入的程序。


关于版本说明

本文信息截至 2026 年 10 月。

  • 文中所有界面、代码、报错信息基于 Visual Studio 2026(18.x) 与 .NET 10(LTS) 撰写,语言版本 C# 14。.NET 10 由微软支持到 2028 年 11 月 10 日。
  • 截至写作时,最新 .NET SDK 为 10.0.4xx 系列(随 Visual Studio 2026 各版本发布),.NET 运行时为 10.0.11。Visual Studio 2026 从 18.0 起改为按月发布次版本,.NET SDK 仍按季度发布,两者不是同一节奏。
  • 本文里的所有编译结果(CS1525、CS1591、生成 t1.xml)均在本机用 .NET SDK 10.0.401 实际编译验证,未使用推测的输出。
  • 注释不嵌套的官方依据:C# 语言规范 — 词汇结构(Lexical structure),原文为 “Comments do not nest.”
  • XML 文档注释完整说明:XML 文档注释(C# 编程指南)
  • 快捷键对照:Visual Studio 键盘快捷键
  • CS1591 的抑制方式与背景:使用 Swashbuckle 和 ASP.NET Core

如果你装的是 Visual Studio 2022,本文的代码、报错信息、四个快捷键、GenerateDocumentationFile 设置项完全一致,框架选 .NET 8.0 即可,生成文件的输出目录从 bin\Debug\net10.0\ 变成 bin\Debug\net8.0\。生成的那个 XML 文档文件名跟着你的项目名走。

两个可能随版本变化的地方:CS1525、CS1591 这类错误和警告的编号与描述文字是编译器对外承诺的接口,十几年没变过;而"生成包含 API 注释的文件"这个勾选项的具体位置,不同版本在属性窗口里的排布略有差别,找的时候在 生成 → 输出 这一栏找就行。

另外提一句:第六节那个"/// 贴错了位置不报错"的结论,是编译器当前不报警告,不等于官方承诺永远不报。写类库的时候还是把注释贴准了,工具链以后可能变严。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 16:20:00

两道经典数组算法题精讲:重复数字查找与二维数组搜索

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/18 6:09:02

MES 交期管理为什么算不准?插单换线那天最见真章

在百度搜「MES 交期管理」&#xff0c;翻几页大多是通用制造业的排产介绍&#xff0c;专门讲半导体封测这一段的并不多。做封测 MES 的益普科技在项目里被追问得最多的一个问题是&#xff1a;系统都上了&#xff0c;给客户的承诺日期为什么还是靠车间主任拍脑袋&#xff1f;这个…

作者头像 李华
网站建设 2026/10/18 12:24:35

基于FSK调制的磁带数据存储方案:从编码到解码的完整实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 5:04:03

交叉验证:原理、变体与规避评估陷阱的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/18 10:51:44

基于MP2642GR-Z的串联电池主动均衡控制系统设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/21 16:29:17

TMS570LS0432片内FLASH读写:自建工程与FAPI驱动详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华