首页 / C# 入门教程 / 类与对象

C# 入门教程

类与对象

本教程共 100 篇 · 第 28 篇 · 更新于 2026-07-31 · 约 8 分钟阅读

C#C# 入门教程编程语言对象面向对象

28. 类与对象

本节目标:理解类是一张蓝图,对象是按蓝图造出的实例,并会定义字段、写方法、用 new 创建对象。

为什么需要”类”

写程序越往后,你会发现光有 intstring 这种零散变量不够用。描述一个”学生”,他需要名字、年龄、成绩,还要能选课、能打印简历。把这些数据和行为各放各的,既难管理又容易乱。

类(class)就是为解决这件事而生:它把”一类事物长什么样(数据)“和”能做什么(行为)“打包成一个自定义类型。这正是面向对象编程(object-oriented programming,OOP)的起点,也是 C# 这类语言组织代码的基石。

类是一张蓝图

类本身不是那个具体的人或物,而是一张”设计图”。比如 Person 描述”人”这种概念:有名字、有年龄,能打招呼。真正按图造出来的”那个叫小明的人”,才叫对象(object),也叫实例(instance)。

Note

记住一句口诀:类是图纸,对象是照图造出的实物。你家里有”手机”这个类吗?没有,你手里那台才是对象;“手机”只是对它共性的一张抽象描述。

定义与使用一个类

先看看用起来是什么样,再回头看类的定义:

namespace CSharpDemo;

// 用起来:new 一个对象,给字段赋值,调用方法
Person p = new();
p.Name = "小明";
p.Age = 20;
p.Introduce();   // 输出:我是小明,20岁

// 类的定义(类型声明写在顶级语句之后)
class Person
{
    public string Name = "";   // 字段:姓名
    public int Age;            // 字段:年龄

    public void Introduce()    // 方法:打招呼
    {
        Console.WriteLine($"我是{Name}{Age}岁");
    }
}
Note

注意这里的写法:顶级语句(使用对象的代码)写在前面,类的定义写在后面。这是 C# 顶级语句(top-level statements)的要求——类型声明必须放在语句之后。代码能正常编译运行,放心复制。类只是图纸,要用 new 才能”施工”出真实对象。

字段:对象的状态

字段(field)是类里存数据的变量,表示对象当前”是什么样”。上面 NameAge 就是字段,它们构成了对象的状态。

Tip

类成员默认是 private(私有),类外访问不到。这里写 public 是为了能在类外面读写,方便演示。访问修饰符(谁能看、谁能改)下一章专门细讲。

方法:对象的行为

方法(method)是类里的一段代码,表示对象能做的”动作”。Introduce 就是 Person 的一个行为,它会用对象自己的字段做事。在面向对象里,方法就是”对象的行为”的载体。

用 new 创建对象

类只是图纸,要用 new 才能”施工”出真实对象。C# 9 起可用 new() 让编译器推断类型,少写一遍类型名。

namespace CSharpDemo;

Person p = new();   // 等价于 new Person()
p.Name = "小明";
p.Introduce();

class Person
{
    public string Name = "";
    public void Introduce() => Console.WriteLine($"我是{Name}");
}
Note

变量 p 存的不是对象”本身”,而是对象在内存里的”地址”(引用,reference),指向堆上的那个对象。把 p 赋给另一个变量,两个变量会指向同一个对象,而不是各自复印一份。

多个对象各自独立

每次 new 都得到一个全新对象,字段互不干扰:

namespace CSharpDemo;

Person a = new();
a.Name = "小明";

Person b = new();
b.Name = "小红";

Console.WriteLine(a.Name);  // 小明
Console.WriteLine(b.Name);  // 小红

class Person
{
    public string Name = "";
}

引用共享的小实验

变量存的是”引用”(对象在内存中的地址),所以两个变量指向同一个对象时,改一个另一个也跟着变:

namespace CSharpDemo;

Person a = new();
a.Name = "小明";

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

Console.WriteLine(a.Name);  // 小刚(a 也变了)

class Person
{
    public string Name = "";
}
Tip

这是”引用类型(reference type)“的核心特征,正好和后面要学的 struct(值类型,赋值会复制整份数据)相反。理解引用共享,能帮你避开很多”明明没改它却变了”的隐蔽 bug。

现代简写:主构造器

C# 12 起支持主构造器(primary constructor),把参数直接写在类名后的括号里,省去手动声明字段再赋值的样板代码:

namespace CSharpDemo;

Person p = new("小明", 20);
p.Introduce();   // 输出:我是小明,20岁

class Person(string Name, int Age)
{
    public void Introduce() => Console.WriteLine($"我是{Name}{Age}岁");
}

括号里的 NameAge 自动成为类内可用的参数,构造时直接传值,相当于”先声明字段、再在构造里赋值”的简写。

Tip

主构造器是语法糖,初学先掌握传统写法,再认识这个简写即可。本教程后续很多示例会用到它,看到 class X(int Id) 这种形式别慌。

构造函数的预告

new Person() 实际调用了一个”构造函数(constructor)“,负责对象出生时的初始化。上面用的是编译器自动给的”无参构造”,构造函数专章会讲如何自定义它。现在只要知道:对象一出生,就由构造函数把它安顿好。

什么时候该用类

  • 一组数据经常一起出现(用户有 id、名字、邮箱)→ 用类打包。
  • 数据要配套操作(订单能算总价、能打印)→ 操作写成方法。
  • 会有多个”同类但内容不同”的个体(多个用户、多个商品)→ 类 + 多次 new

只想临时算两个数,一个独立方法就够了,不必硬造类。

常见坑

  1. 忘了 new:声明 Person p; 就直接 p.Name = ...,此时 pnull,运行报空引用异常。必须先 new
  2. 误以为赋值会复制:把 a 赋给 b,改 b 会影响 a(同一对象)。要独立副本得另行拷贝。
  3. 字段未初始化就读取:数值字段默认 0、引用字段默认 null,字符串字段建议给 = "" 默认值更稳。
Warning

引用类型”赋值即共享”最容易翻车。当你疑惑”数据怎么自己变了”,先想想是不是两个变量指向了同一个对象。

最佳实践

  • 用类把”相关数据 + 操作”聚到一起,别让零散变量满天飞。
  • 初学显式用 public 字段便于练习,真实项目更推荐用”属性(property)“封装(后续章节讲)。
  • class X(int Id) 主构造器写法,理解它等价于”先声明字段、再在构造里赋值”。
  • 对象用前确保 new 过,引用字段给合理默认值。

类 vs 结构体:以后会讲

C# 里除了 class,还有 struct(结构体)。关键区别:class 是引用类型,赋值共享;struct 是值类型,赋值复制整份数据。描述”有身份、要共享”的事物(人、订单)用 class;描述”轻量、纯数据”的小结构(坐标、颜色)更适合 struct。这块后面有专章对比,现在知道有这两种选择即可。

对象用完会怎样

new 出来的对象放在”堆”上,不用时由垃圾回收器(Garbage Collection,GC)自动清理,你基本不用手动释放。这和 C/C++ 要自己 free 不同,是 C# 让人省心的地方。只有涉及文件、网络等非托管资源时,才需要 using 释放,那是后面的话题。

Tip

初学只要记住:普通对象只管 new 着用,内存有 GC 兜底,别总想着手动”释放”。

小结

类是蓝图,对象是实例;字段存状态,方法写行为;new 把图纸变成真实对象。理解”引用共享”是面向对象第一块基石。下一章我们给成员加上”谁能看、谁能改”的边界——访问修饰符。