CodeGym /课程 /C# SELF /OOP代码风格和可读性小贴士

OOP代码风格和可读性小贴士

C# SELF
第 25 级 , 课程 4
可用

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() { ... }

方法名要体现动作(PrintGetSaveCalculate等),这样一看就知道会发生啥。

字段和属性的命名

字段一般是private,用小写字母加camelCase,经常带下划线:

private int _count;
private Student _owner;

属性PascalCase,因为是类的外部接口:

public int Balance { get; set; }

变量

局部变量camelCase,越短越贴合上下文越好:

string inputName;
int studentCount;

拜托,像a1result2something这种变量名,除非你想给下个月的自己挖坑。

3. 类结构的组织

类成员排得好,导航方便,也能一眼看出啥跟啥。

一般顺序如下:

  1. 构造函数
  2. 属性
  3. 方法
  4. 嵌套类型(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。只有继承类需要才protectedpublic只给外部用。

不推荐:

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}");
    }
}
1
调查/小测验
继承时的错误第 25 级,课程 4
不可用
继承时的错误
声明类和对象时常见的错误
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION