C# 代码审查:检查什么以及如何在实际中提供反馈
代码审查不仅仅是合并拉取请求前的形式化流程。它是提升代码质量、在团队中传播知识以及预防错误的强大工具。对于 C# 和 .NET 生态系统尤其如此,因为其中涉及许多细微之处:从内存管理和异步操作,到强类型和 LINQ。
在本文中,我们将详细分析审查 C# 代码时应具体关注哪些方面,以及如何提供反馈,让您的意见被倾听,而不是被讨厌。
1. 架构与逻辑:“我们为什么要这样做?”
在查看格式化和变量命名之前,请确保所解决的问题本身是有意义的。这是最重要但经常被忽略的步骤。
- 符合需求:代码是否解决了工单中描述的具体业务问题?是否存在多余的功能(YAGNI)?
- 违反 SOLID 原则:类是否变成了“上帝对象”?是否有清晰的职责分离?例如,业务逻辑是否与数据访问逻辑混合在一起?
- 过度复杂:问题能否更简单地解决?有时开发人员会编写复杂的模式,而实际上只需要一个简单的
if-else或循环。
// ❌ 不好:类做了太多事情public class UserService{ public void RegisterUser(string email, string password) { // 验证 if (!email.Contains("@")) throw new Exception("Invalid email");
// 密码哈希 var hash = BCrypt.HashPassword(password);
// 保存到数据库 using var db = new AppDbContext(); db.Users.Add(new User { Email = email, PasswordHash = hash }); db.SaveChanges();
// 发送邮件 SmtpClient.Send("welcome@site.com", email, "Welcome!"); }}
// ✅ 好:分层设计(单一职责原则)public class UserRegistrationService{ private readonly IUserRepository _repository; private readonly IEmailService _emailService;
public UserRegistrationService(IUserRepository repository, IEmailService emailService) { _repository = repository; _emailService = emailService; }
public async Task<Result> RegisterAsync(string email, string password) { if (!EmailValidator.IsValid(email)) return Result.Failure("Invalid email");
var user = User.Create(email, password); await _repository.AddAsync(user); await _emailService.SendWelcomeAsync(email);
return Result.Success(); }}2. 性能与安全:“这会不会搞垮服务器?”
.NET 是一个强大的框架,但很容易被误用。以下是每次审查中应检查的内容。
- 异步(async/await):异步代码中是否存在阻塞调用(
.Result、.Wait())?这会扼杀性能。在库中使用ConfigureAwait(false)。 - 内存泄漏:是否忘记释放
IDisposable资源?是否对Stream、SqlConnection等使用了using? - SQL 注入:是否通过字符串拼接构建查询?在现代 C# 中使用 Entity Framework 或 Dapper 时这很少见,但必须检查。
- LINQ 和集合:是否对同一集合进行了多次遍历?是否使用
Any()代替Count() > 0来检查元素是否存在?
// ❌ 不好:阻塞调用和多次遍历var task = GetDataAsync();var data = task.Result; // 线程阻塞!
if (data.Count() > 0) // 第一次遍历