ZetCode

C# 类

最后修改于 2023 年 7 月 5 日

在本文中,我们将展示如何在 C# 中定义类。

关键字 class 用于定义类,类是创建对象的模板。 这些对象被称为类的实例。 使用 new 关键字创建一个新类。

在类中,我们定义成员字段和成员函数。 在类中定义的函数称为方法。 成员字段和函数通过点运算符访问。

C# 简单类示例

以下示例创建一个简单的类。

Program.cs
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 类。 该类有两个属性:NameOccupation。 属性使用访问器,通过访问器可以读取、写入或操作成员字段的值。

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 拥有一个庞大的类库,程序员可以使用它们。

Program.cs
using System.Text;

var path = "words.txt";

string content = File.ReadAllText(path, Encoding.UTF8);
Console.WriteLine(content);

例如,在这个小程序中,我们使用 File 类来读取文件的内容,并使用 Console 类将内容写入终端。

类的可读表示形式

为了提供类的可读表示形式,我们重写 ToString 方法。

Program.cs
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 关键字创建。 我们可以创建抽象方法和成员字段。

抽象类不能被实例化,抽象方法不能被实现。

Program.cs
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# 嵌套类

嵌套类是在另一个类的正文中定义的内部类。 当嵌套类与外部类密切相关时,定义嵌套类是有意义的。

Program.cs
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 关键字,可以将类的定义拆分为同一命名空间内的多个部分。 该类也可以在多个文件中定义。

当处理非常大的代码库时,可以使用分部类,它可以被拆分为更小的单元。 分部类也与自动代码生成器一起使用。

Program.cs
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 关键字用于防止从类进行意外派生。 密封类不能是抽象类。

Program.cs
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` 派生。

来源

类介绍

在本文中,我们展示了如何定义类并描述了各种类型的类。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 我从 2007 年开始撰写编程文章。 迄今为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 C# 教程