类与对象
为什么需要类
C# 是一门面向对象的语言,几乎一切皆对象。之前我们用顶层语句写代码,但真正的 C# 程序都由类构成。类是对象的蓝图——定义了数据(字段)和行为(方法),而对象是类的具体实例。
类的定义
用 class 关键字定义类,类名使用帕斯卡命名法(每个单词首字母大写)。
CSHARP
class Person
{
public string Name;
public int Age;
public void SayHello()
{
System.Console.WriteLine($"你好,我是{Name},今年{Age}岁。");
}
}
public表示外部可以访问该成员Name、Age是字段(存储数据)SayHello是方法(定义行为)
对象的创建
用 new 关键字根据类创建对象:
CSHARP
Person p = new Person();
p.Name = "小明";
p.Age = 18;
p.SayHello();
TEXT
你好,我是小明,今年18岁。
每个 new 创建一个独立的对象,拥有自己的字段副本。
字段与字段初始化
字段可以在声明时直接赋初始值:
CSHARP
class Student
{
public string Name = "未知";
public int Score = 0;
}
若未赋初值,数值类型默认为 0,引用类型默认为 null。
访问修饰符控制字段的可见性:
| 修饰符 | 含义 |
|---|---|
public |
任何地方都可访问 |
private |
仅类内部可访问(默认) |
通常将字段设为 private,通过方法或属性控制访问。
示例
CSHARP
using System;
class BankAccount
{
private decimal balance = 1000m;
public void Deposit(decimal amount)
{
balance += amount;
Console.WriteLine($"存入{amount},余额{balance}");
}
public void ShowBalance()
{
Console.WriteLine($"当前余额:{balance}");
}
}
class Program
{
static void Main()
{
BankAccount acc = new BankAccount();
acc.ShowBalance();
acc.Deposit(500m);
}
}
TEXT
当前余额:1000
存入500,余额1500
方法
方法是类中定义的函数,描述对象的行为。方法可以访问同一个类中的字段:
CSHARP
class Calculator
{
private int result = 0;
public void Add(int value)
{
result += value;
}
public int GetResult()
{
return result;
}
}
this 关键字
this 指向当前对象实例,最常见的用途是区分字段与同名参数:
CSHARP
class Person
{
public string Name;
public int Age;
public Person(string Name, int Age)
{
this.Name = Name;
this.Age = Age;
}
}
this.Name指字段,Name指参数- 没有歧义时可以省略
this
构造函数
构造函数在创建对象时自动调用,用于初始化对象。
无参构造函数
如果不定义任何构造函数,编译器自动生成一个无参构造函数:
CSHARP
class Dog
{
public string Name;
public Dog()
{
Name = "无名";
}
}
有参构造函数
CSHARP
class Dog
{
public string Name;
public Dog(string name)
{
Name = name;
}
}
⚠️ 一旦定义了任何构造函数,编译器不再自动生成无参构造函数。
构造函数重载
可以定义多个构造函数,参数不同:
CSHARP
class Dog
{
public string Name;
public int Age;
public Dog()
{
Name = "无名";
Age = 0;
}
public Dog(string name)
{
Name = name;
Age = 0;
}
public Dog(string name, int age)
{
Name = name;
Age = age;
}
}
构造函数链
用 this(...) 让一个构造函数调用另一个,避免重复代码:
CSHARP
class Dog
{
public string Name;
public int Age;
public Dog() : this("无名", 0) { }
public Dog(string name) : this(name, 0) { }
public Dog(string name, int age)
{
Name = name;
Age = age;
}
}
示例
CSHARP
using System;
class Book
{
public string Title;
public string Author;
public decimal Price;
public Book() : this("未知", "未知", 0m) { }
public Book(string title, string author) : this(title, author, 29.9m) { }
public Book(string title, string author, decimal price)
{
Title = title;
Author = author;
Price = price;
}
public void PrintInfo()
{
Console.WriteLine($"《{Title}》 作者:{Author} 价格:{Price}元");
}
}
class Program
{
static void Main()
{
Book b1 = new Book();
Book b2 = new Book("C#入门", "张三");
Book b3 = new Book("深入C#", "李四", 59.9m);
b1.PrintInfo();
b2.PrintInfo();
b3.PrintInfo();
}
}
TEXT
《未知》 作者:未知 价格:0元
《C#入门》 作者:张三 价格:29.9元
《深入C#》 作者:李四 价格:59.9元
析构函数
析构函数在对象被垃圾回收前调用,语法为 ~类名():
CSHARP
class Resource
{
~Resource()
{
Console.WriteLine("对象被回收");
}
}
📌 C# 有自动垃圾回收机制(GC),大多数情况不需要手动写析构函数。它只用于释放非托管资源(如文件句柄、数据库连接),后续课程会详细讨论。
对象初始化器
C# 3.0 引入的对象初始化器语法,可以在 new 时直接给公共字段或属性赋值:
CSHARP
Person p = new Person { Name = "小红", Age = 20 };
等价于:
CSHARP
Person p = new Person();
p.Name = "小红";
p.Age = 20;
对象初始化器可以与有参构造函数组合使用:
CSHARP
Person p = new Person("小红") { Age = 20 };
示例
CSHARP
using System;
class Rectangle
{
public double Width = 1;
public double Height = 1;
public double Area()
{
return Width * Height;
}
}
class Program
{
static void Main()
{
Rectangle r1 = new Rectangle();
Rectangle r2 = new Rectangle { Width = 5, Height = 3 };
Rectangle r3 = new Rectangle { Width = 10 };
Console.WriteLine($"r1 面积:{r1.Area()}");
Console.WriteLine($"r2 面积:{r2.Area()}");
Console.WriteLine($"r3 面积:{r3.Area()}");
}
}
TEXT
r1 面积:1
r2 面积:15
r3 面积:10
new 与 null 的区别
| 概念 | 含义 |
|---|---|
new ClassName() |
在堆上创建对象,返回对象引用 |
null |
不指向任何对象,是引用类型的默认值 |
CSHARP
Person p1 = new Person();
Person p2 = null;
Console.WriteLine(p1 == null);
Console.WriteLine(p2 == null);
TEXT
False
True
⚠️ 对 null 引用访问成员会抛出 NullReferenceException,这是 C# 最常见的运行时错误:
CSHARP
Person p = null;
p.SayHello();
💡 使用前检查是否为 null:
CSHARP
if (p != null)
{
p.SayHello();
}
❓ 常见问题
Q 不写构造函数会怎样?
A 编译器自动生成一个无参构造函数,字段赋默认值。
Q 定义了有参构造函数后还能用无参创建对象吗?
A 不能,除非手动再定义一个无参构造函数。
Q this 能在静态方法中使用吗?
A 不能,this 指当前实例,静态方法不关联实例。
Q 对象初始化器能赋值 private 字段吗?
A 不能,只能初始化可访问的成员(public 字段或属性)。
Q null 和 0 是一回事吗?
A 不是。null 表示"无引用",0 是数值类型的值。值类型不能为 null。
📖 小节
- 类是对象的蓝图,用
class定义 - 对象用
new创建,每个对象独立拥有字段副本 - 字段存数据,方法定义行为,
public/private控制访问 this指当前实例,常用于区分字段与同名参数- 构造函数在创建对象时自动调用,可重载,可用
this(...)链式调用 - 析构函数由 GC 自动调用,一般无需手写
- 对象初始化器
new T { Field = value }简化赋值 new创建对象,null表示无对象引用,访问 null 成员会报错
📝 作业
- 定义一个
Car类,包含Brand(string)、Speed(int)字段,一个Accelerate(int amount)方法使 Speed 增加,一个无参构造函数将 Speed 初始化为 0 - 为
Car类添加有参构造函数Car(string brand),并用this(...)实现构造函数链 - 用对象初始化器创建一个
Car对象并设置 Brand 和 Speed,然后调用 Accelerate 方法,打印最终 Speed - 编写代码演示:创建一个
Car引用赋为null,尝试访问其成员,用 try-catch 捕获NullReferenceException并打印提示信息



