C#代码审查:检查什么才能让代码不生病

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C#代码审查:不只是打个勾,而是拯救生产环境

\n\n

你是否见过那种能运行,但让人不忍直视的代码?“魔法数字”、循环嵌套、async void以及不该出现null的地方。C#代码审查不是官僚流程,而是bug进入生产环境前的最后一道防线。或者更糟的是,在您的同事开始维护这段代码并诅咒作者之前。

\n\n

在本文中,我们将分析审查C#代码时真正需要关注的内容。没有废话——只有具体的案例、反模式和示例。如果您是初级开发者——这是您的检查清单。如果您是高级开发者——请刷新记忆。我们开始吧。

\n\n

1. Null——C#开发者的头号敌人

\n\n

著名的NullReferenceException是数百万个不眠之夜的罪魁祸首。代码审查中首先要检查的是:对null的防护。

\n\n

哪些情况需要警惕?

\n
    \n
  • 访问属性前缺少对null的检查。
  • \n
  • 在期望返回集合的方法中返回null。
  • \n
  • 忽略可为空上下文(#nullable enable)。
  • \n
\n\n

不好的写法:

\n
public string GetUserName(User user)\n{\n    return user.Name.ToUpper(); // user可能为null!\n}
\n\n

好的写法(C# 8+):

\n
public string GetUserName(User? user)\n{\n    return user?.Name?.ToUpper() ?? "Unknown";\n}
\n\n

代码审查建议:要求在新项目中启用Nullable。这不仅时髦,还能避免愚蠢的错误。没有检查nullable的C#代码审查就像不系安全带开车。

\n\n

2. 异步:async/await避免踩坑

\n\n

C#中的异步编程是一个强大的工具,但如果使用不当,就会变成一颗定时炸弹。在审查中,我们检查三个主要错误。

\n\n

错误#1:async void

\n

async void方法无法被追踪——异常会落入最终线程并杀死进程。仅允许用于事件处理程序(例如WinForms中的按钮)。

\n\n

不好的写法:

\n
public async void LoadDataAsync()\n{\n    var data = await _service.GetDataAsync(); // 错误会杀死进程\n}
\n\n

好的写法:

\n
public async Task LoadDataAsync()\n{\n    var data = await _service.GetDataAsync();\n}
\n\n

错误#2:阻塞异步代码

\n

在异步上下文中使用.Result或.Wait()是导致死锁的可靠途径。

\n\n

不好的写法:

\n
var result = _service.GetDataAsync().Result; // 在UI应用程序中会导致死锁
\n\n

好的写法:

\n
var result = await _service.GetDataAsync();
\n\n

错误#3:缺少CancellationToken

\n

长时间运行的操作应该是可取消的。如果方法签名中没有CancellationToken,请询问作者:“如果用户关闭标签页会怎样?”

\n\n

3. LINQ:优雅还是慢性死亡?

\n\n

LINQ很优雅。但代码审查经常揭示,在优雅背后隐藏着O(n²)或对集合的多次遍历。

\n\n

审查C#代码时使用LINQ的典型错误:

\n
    \n
  • 多次遍历:.Count() > 0 + .First()——两次遍历。请使用.Any()和.FirstOrDefault()。
  • \n
  • 忘记ToList():延迟加载可能导致在DataReader上下文已关闭后执行数据库查询。
  • \n
  • Where + Select = 冗余:如果可以使用一个SelectMany——请使用它。
  • \n
\n\n

应该触发红色警报的示例:

\n
var result = l                

博客

书籍推荐