写程序的人都听过"面向对象",而 C# 是一门从出生起就围绕 class 设计的语言。这一篇只解决一件事:怎么用 class 把数据和操作打包成一个类型,并创建它的实例。

最小的类长什么样

类是"图纸",对象是照着图纸造出来的具体实例。

class Dog
{
    public string Name;   // 字段:这只狗叫什么
    public int Age;

    public void Bark()    // 方法:这只狗会做什么
    {
        Console.WriteLine($"{Name}:汪汪!");
    }
}

class Program
{
    static void Main()
    {
        Dog d = new Dog();
        d.Name = "旺财";
        d.Age = 2;
        d.Bark();          // 输出:旺财:汪汪!
    }
}

new Dog() 就是按图纸造对象,d 里存的是对那个对象的引用。d.Name = "旺财" 只改了这一只,别的对象不受影响。

构造函数:创建时就初始化

每次 new 完再一个个赋值太啰嗦。构造函数让你在创建对象的同时完成初始化,方法里引用"当前对象"用 this。

class Dog
{
    public string Name;
    public int Age;

    public Dog(string name, int age)   // 与类同名、没有返回类型
    {
        this.Name = name;   // this.Name 是字段,name 是参数
        this.Age = age;
    }
}

// 使用
Dog d = new Dog("旺财", 2);
Console.WriteLine(d.Age);   // 输出:2

一个类可以有多个构造函数,参数不同即可,编译器按你传的参数挑一个执行。

属性:比公开字段更稳的写法

把字段直接设为 public,等于谁都能随便改。属性让你像访问字段一样读写,内部却可以加逻辑。

class Dog
{
    private int age;              // 私有字段,外面摸不到

    public int Age
    {
        get { return age; }
        set
        {
            if (value < 0) value = 0;   // 年龄不允许为负
            age = value;
        }
    }
}

// 使用
Dog d = new Dog();
d.Age = -5;
Console.WriteLine(d.Age);   // 输出:0

如果不需要校验逻辑,还可以写自动属性 public int Age { get; set; },一行搞定。

对象是引用类型

Dog a = new Dog();
a.Name = "旺财";

Dog b = a;          // b 和 a 指向同一个对象
b.Name = "小黑";

Console.WriteLine(a.Name);   // 输出:小黑

a 和 b 存的都是"地址",改 b 就是改 a 看到的那只狗。这一点和 int 这类值类型完全不同,初学时最容易在这里犯迷糊。

小结

  • class 是图纸,new 出来的每个对象互相独立
  • 构造函数与类同名、无返回类型,负责创建时初始化,可以重载
  • 属性(get/set)在"像字段一样好用"和"内部可控"之间取得平衡
  • 对象变量存的是引用,赋值传过去的是同一个对象

下一篇可以试着给 Dog 加上继承,体会一下多态。