C# 类
最后修改于 2023 年 7 月 5 日
在本文中,我们将展示如何在 C# 中定义类。
关键字 class
用于定义类,类是创建对象的模板。 这些对象被称为类的实例。 使用 new
关键字创建一个新类。
在类中,我们定义成员字段和成员函数。 在类中定义的函数称为方法。 成员字段和函数通过点运算符访问。
C# 简单类示例
以下示例创建一个简单的类。
var u = new User("John Doe", "gardener"); Console.WriteLine($"{u.Name} is a {u.Occupation}"); u.Occupation = "driver"; Console.WriteLine($"{u.Name} is a {u.Occupation}"); class User { public User(string name, string occupation) { this.Name = name; this.Occupation = occupation; } public string Name { get; set; } public string Occupation { get; set; } }
在该程序中,我们定义了 User
类。 该类有两个属性:Name
和 Occupation
。 属性使用访问器,通过访问器可以读取、写入或操作成员字段的值。
var u = new User("John Doe", "gardener");
我们创建 User
类的一个新实例。 我们将两个参数传递给构造函数。 构造函数是在创建对象时调用的方法。
Console.WriteLine($"{u.Name} is a {u.Occupation}");
我们访问 User
类的两个属性。
class User { ... }
关键字 class
定义一个类。 类的正文写在 {}
括号内。
public User(string name, string occupation) { this.Name = name; this.Occupation = occupation; }
这是类的构造函数。 构造函数与类同名。 它在构造对象时被调用。 在构造函数内部,我们设置两个属性。
public string Name { get; set; } public string Occupation { get; set; }
我们定义了两个属性。 自动实现的属性为定义类提供了一种简洁的语法。
$ dotnet run John Doe is a gardener John Doe is a driver
C# 标准类
.NET 拥有一个庞大的类库,程序员可以使用它们。
using System.Text; var path = "words.txt"; string content = File.ReadAllText(path, Encoding.UTF8); Console.WriteLine(content);
例如,在这个小程序中,我们使用 File
类来读取文件的内容,并使用 Console
类将内容写入终端。
类的可读表示形式
为了提供类的可读表示形式,我们重写 ToString
方法。
var u = new User("John Doe", "gardener"); Console.WriteLine(u); class User { public User(string name, string occupation) { this.Name = name; this.Occupation = occupation; } public string Name { get; set; } public string Occupation { get; set; } public override string ToString() { return $"{this.Name} is a {this.Occupation}"; } }
在该程序中,我们创建了自己的 ToString
方法的实现。
var u = new User("John Doe", "gardener"); Console.WriteLine(u);
当我们把 user 实例传递给 Console.WriteLine
方法时,ToString
方法会被调用。
C# 抽象类
抽象类是一个未完成的类,其目的是为其子类定义一些通用定义。 它必须在其子类中实现。 抽象类使用 abstract 关键字创建。 我们可以创建抽象方法和成员字段。
抽象类不能被实例化,抽象方法不能被实现。
var c = new Circle(12, 45, 22); Console.WriteLine(c); Console.WriteLine($"Area of circle: {c.Area()}"); Console.WriteLine(c.GetCoordinates()); Console.WriteLine("---------------------"); var s = new Square(10, 20, 50); Console.WriteLine(s); Console.WriteLine($"Area of square: {s.Area()}"); Console.WriteLine(s.GetCoordinates()); abstract class Drawing { protected int x = 0; protected int y = 0; public abstract double Area(); public string GetCoordinates() { return $"x: {x}, y: {y}"; } } class Circle : Drawing { private int r; public Circle(int x, int y, int r) { this.x = x; this.y = y; this.r = r; } public override double Area() { return this.r * this.r * Math.PI; } public override string ToString() { return $"Circle at x: {x}, y: {x}, radius: {r}"; } } class Square : Drawing { private int width; public Square(int x, int y, int width) { this.x = x; this.y = y; this.width = width; } public override double Area() { return this.width * this.width; } public override string ToString() { return $"Square at x: {x}, y: {y}, w: {width}"; } }
我们有一个抽象的基类 Drawing。该类定义了两个成员字段,定义了一个方法并声明了一个方法。其中一个方法是抽象的,另一个方法是完全实现的。 Drawing 类是抽象的,因为我们无法绘制它。 我们可以绘制一个圆、一个点或一个正方形。Drawing 类对于我们可以绘制的对象具有一些通用功能。
abstract class Drawing
我们使用 abstract
关键字来定义一个抽象类。
public abstract double Area();
抽象方法也以 abstract
关键字开头。
class Circle : Drawing
Circle 是一个具体的类,它可以绘制在表面上。 我们将其定义为 Drawing
类的子类;因此,它必须实现抽象的 Area
方法。
public override double Area() { return this.r * this.r * Math.PI; }
当我们实现 Area
方法时,我们必须使用 override
关键字。 这样我们通知编译器我们重写了一个现有的(继承的)方法。
$ dotnet run Circle at x: 12, y: 12, radius: 22 Area of circle: 1520.53084433746 x: 12, y: 45 --------------------- Square at x: 10, y: 20, w: 50 Area of square: 2500 x: 10, y: 20
C# 嵌套类
嵌套类是在另一个类的正文中定义的内部类。 当嵌套类与外部类密切相关时,定义嵌套类是有意义的。
var fjet = new FighterJet(); fjet.TakeOff(); fjet.DropBomb(); fjet.DropBomb(); fjet.DropBomb(); fjet.Land(); class FighterJet { public void TakeOff() { Console.WriteLine("FighterJet takes off"); } public void Land() { Console.WriteLine("FighterJet lands"); } public void DropBomb() { var bomb = new Bomb(); bomb.Drop(); } class Bomb { public Bomb() { Console.WriteLine("Bomb prepared"); } public void Drop() { Console.WriteLine("Bomb launched"); } } }
我们有一个 FighterJet
类,它可以投掷炸弹。 炸弹对象可以定义为嵌套类,因为它可能被认为是外部类的组成部分。
$ dotnet run FighterJet takes off Bomb prepared Bomb launched Bomb prepared Bomb launched Bomb prepared Bomb launched FighterJet lands
C# 分部类
使用 partial
关键字,可以将类的定义拆分为同一命名空间内的多个部分。 该类也可以在多个文件中定义。
当处理非常大的代码库时,可以使用分部类,它可以被拆分为更小的单元。 分部类也与自动代码生成器一起使用。
namespace PartialClass; partial class Worker { public string DoWork() { return "Doing work"; } } partial class Worker { public string DoPause() { return "Pausing"; } } class Program { static void Main(string[] args) { var worker = new Worker(); Console.WriteLine(worker.DoWork()); Console.WriteLine(worker.DoWork()); Console.WriteLine(worker.DoPause()); } }
在该示例中,我们有一个 Worker
类,它被定义为两个部分。 这两个部分由编译器连接在一起以形成最终的类。
$ dotnet run Doing work Doing work Pausing
C# 密封类
sealed
关键字用于防止从类进行意外派生。 密封类不能是抽象类。
namespace DerivedMath; sealed class Math { public static double GetPI() { return 3.141592; } } class Derived : Math { public void Say() { Console.WriteLine("Derived class"); } } class Program { static void Main(string[] args) { var dm = new Derived(); dm.Say(); } }
在上面的程序中,我们有一个基类 Math
。 这个类的唯一目的是为程序员提供一些有用的方法和常量。(在我们的例子中,为了简单起见,我们只有一个方法。) 它不是为了被继承而创建的。
为了防止其他不知情的程序员从此类派生,创建者使该类为 sealed
。 如果您尝试编译此程序,您会收到以下错误: 'Derived' 无法从密封类型 `Math` 派生。
来源
在本文中,我们展示了如何定义类并描述了各种类型的类。
作者
列出所有 C# 教程。