1. 引言
“干净的代码”不是啥神圣不可侵犯的东西,而是程序员活下去的真本事。任何OOP项目,不管多完美,很快都会堆一堆类、字段、方法、各种骚操作……如果结构和美感一乱,一周后你自己都看不懂自己写的啥。想了解“生存之战”可以看看Robert Martin的《Clean Code》,就是讲这些战斗的。
代码风格不是“谁喜欢咋写就咋写”,而是让大家都能活得轻松点:
- 同事(或者你自己)能秒懂发生了啥。
- 错误(尤其是架构上的)一眼就能看出来。
- 代码好维护,改起来不容易出锅。
来看看怎么让OOP代码让老师、同事、甚至linter都爱不释手。
2. 命名:你的第一道防线
类的命名
类在C#里一般用PascalCase(每个单词首字母大写,比如:MyNewClass),名字要能直接回答“这是什么?”。名字最好用名词!
public class StudentAccount { /* ... */ }
public class InvoiceGenerator { /* ... */ }
不推荐:
class doMagic { ... } // 不好:啥魔法?PascalCase也没用对。
方法的命名
方法也用PascalCase,但最好用“动词+对象”:
public void PrintReport() { ... }
public string GetFormattedName() { ... }
方法名要体现动作(Print、Get、Save、Calculate等),这样一看就知道会发生啥。
字段和属性的命名
字段一般是private,用小写字母加camelCase,经常带下划线:
private int _count;
private Student _owner;
属性用PascalCase,因为是类的外部接口:
public int Balance { get; set; }
变量
局部变量用camelCase,越短越贴合上下文越好:
string inputName;
int studentCount;
拜托,像a1、result2、something这种变量名,除非你想给下个月的自己挖坑。
3. 类结构的组织
类成员排得好,导航方便,也能一眼看出啥跟啥。
一般顺序如下:
- 构造函数
- 属性
- 方法
- 嵌套类型(enum、class等)
例子:
public class Student
{
// --- 字段 ---
private string _name;
// --- 构造函数 ---
public Student(string name)
{
_name = name;
}
// --- 属性 ---
public string Name
{
get => _name;
set => _name = value;
}
// --- 方法 ---
public void PrintInfo()
{
Console.WriteLine($"姓名: {_name}");
}
}
这些“块”用注释分开(// --- 方法 ---),尤其是大类里很有用。JetBrains Rider、Visual Studio等IDE都能快速折叠/展开这些区域。
4. 注释和文档
注释是好东西。但滥用注释或者写“看不懂的代码才解释”,其实还不如直接把代码写清楚!
好注释是解释“为什么”,不是“做了什么”。
// 用Guid做唯一标识,因为系统是分布式的
public Guid Id { get; set; }
方法、类和属性的文档
用xml文档给类和public方法写说明。IDE鼠标悬停时会显示这些描述。
/// <summary>
/// 表示大学生。
/// </summary>
public class Student
{
/// <summary>
/// 学生姓名。
/// </summary>
public string Name { get; set; }
}
哪些注释不用写
- 简单的事(i++ // i加1)。
- 变量名太烂(“// 这里发生了点啥”——对,但啥?)。
5. 分而治之
小类和小方法
黄金法则:一个类只做一件事(见单一职责原则)。如果Student类既管成绩,又管邮件,还管课表——那肯定有问题。
- 类300-400行以内都算正常。再多就该反思了。
- 方法15-20行以内最好。特殊情况除外,比如大case的处理器。
“膨胀”方法的例子:
public void Process()
{
// 通知客户
// 保存更改
// 发送邮件
// 写日志
// ...(15步)
}
更好的写法:
public void Process()
{
NotifyClient();
SaveChanges();
SendEmail();
LogActivity();
}
每个步骤都拆成私有方法,代码更紧凑,也更好测。
6. 实用建议
视觉结构:格式化、缩进、空行
IDE都能自动格式化代码(Visual Studio用Ctrl+K, D,Rider用Ctrl+Alt+L),但基本原则还是要懂。
- 缩进——4个空格。别用Tab,也别用2个空格。
- 空行——方法之间、字段和属性之间、属性和方法之间都要空一行。
- 大括号类和方法的大括号总是新起一行(Allman风格):
public class Test
{
public void Print()
{
Console.WriteLine("Hello");
}
}
“强”和“弱”类成员:访问修饰符
尽量让东西都封闭起来:只开放真的需要外部访问的。字段或方法只在类里用就private。只有继承类需要才protected。public只给外部用。
不推荐:
public string ConnectionString; // 谁都能改!
更好:
private string _connectionString;
public string ConnectionString
{
get => _connectionString;
private set => _connectionString = value;
}
用自动属性
有了自动属性和init-only setter,手写getter/setter就太原始了。
例子:
public string Name { get; set; } // 很棒!
public int Age { get; init; } // 只能初始化时赋值,更安全。
如果需要计算属性:
public string FullName => $"{FirstName} {LastName}";
封装和getter/setter
如果属性有业务逻辑或需要控制,建议用私有字段+带逻辑的getter/setter。
private int _grade;
public int Grade
{
get => _grade;
set
{
if (value < 0) _grade = 0;
else if (value > 100) _grade = 100;
else _grade = value;
}
}
这样你和别人都不容易把对象“搞坏”。
7. 还有一些建议
别怕接口和抽象
接口用来做契约、方便测试、扩展应用。
不推荐:
- 接口只有一个方法,哪都不用;
- 接口只被一个类实现。
- 接口被2个以上类用;
- 接口用来抽象外部系统(比如日志、数据存储)。
写代码要方便测试
好OOP代码的标志之一就是容易测。
- 别写全靠全局变量或静态字段的方法。
- 别怕依赖注入——用构造函数参数传(Dependency Injection)。
- 把计算(逻辑)和用户交互(输入/输出)分开。这样不仅好测,也好维护。
新手常见的坑和反模式
- 别写“上帝类”(God Object),啥都管。
- 别用“魔法数字”不解释(if (status == 42)——为啥42?)。
- 别为了继承而继承——有时候用组合更好(类里有别的类的字段,而不是继承)。
- 别写100行的巨型方法——根本测不了也看不懂。
- 永远给扩展留空间(open/closed principle)。
8. 好代码和烂代码长啥样
烂例子:
class s // 不好:类名小写。
{
public int a; // 没意义,名字烂
public void m() // 不好:方法名就一个字母。
{
Console.WriteLine(a);
// 不好:看不出方法干嘛。
}
}
好例子:
// 表示学生。
public class Student
{
// 学生年龄。
private int _age;
public int Age
{
get => _age;
set => _age = value < 0 ? 0 : value;
}
// 输出学生信息。
public void PrintInfo()
{
Console.WriteLine($"学生年龄: {Age}");
}
}
GO TO FULL VERSION