Menu
CoddyTech

实例数据与静态数据

本课属于 Coddy C# 学习旅程的“面向对象编程”单元。第 15 课,共 70 课。

现在你已经了解了静态成员,让我们来明确何时使用实例数据,何时使用静态数据。这个决定会影响类如何存储和共享信息。

实例数据分别属于每个对象。每个对象都有自己的副本,对一个对象的更改不会影响其他对象:

public class BankAccount
{
    public string Owner { get; set; }      // 实例属性,每个账户各有一个
    public decimal Balance { get; set; }   // 实例属性,每个账户各有一个
}

每个 BankAccount 都有自己的所有者和余额。这很合理,因为不同账户属于不同的人,金额也各不相同。

静态数据属于类本身,并由所有实例共享:

public class BankAccount
{
    public static decimal InterestRate = 0.05m;  // 静态字段,所有账户共用
    public static int TotalAccounts = 0;         // 静态字段,统计所有账户
    
    public string Owner { get; set; }
    public decimal Balance { get; set; }
}

利率对每个账户都相同,因此将其设为静态是合理的。账户总数计数器跟踪的是整个类的信息,而不是单个账户的数据。

一个简单的规则:如果数据描述的是某个特定对象,就把它设为实例属性。如果数据描述的是整个类,或者应该由多个对象共享,就把它设为静态属性。混淆两者会导致 bug,例如数据在不同对象之间意外改变,或在需要时无法访问。

challenge icon

挑战

简单

让我们来构建一个游戏会话追踪器,展示每位玩家各自拥有的数据与整个游戏共享的数据之间的区别。

你将创建两个文件来组织代码:

  • Player.cs:在 GameSession 命名空间中定义一个 Player 类。每位玩家都有自己的 Username(字符串)和 Score(整数),这些数据对每位玩家来说都是独有的。这个类还应追踪适用于所有玩家的信息:一个静态字段 GameName(字符串),用于存储所有人正在玩的游戏名称;以及一个静态字段 TotalPlayers(整数),用于统计已加入的玩家人数。添加一个接收用户名和初始分数的构造函数,并自动增加玩家总数。添加一个静态方法 SetGameName(string name) 来设置游戏名称。
  • Program.cs:在主文件中设置游戏,并根据输入创建玩家。先设置游戏名称,然后创建两位玩家,并显示他们各自的信息以及共享的游戏数据。

你将收到 5 个输入:

  • 游戏名称
  • 第一位玩家的用户名
  • 第一位玩家的初始分数
  • 第二位玩家的用户名
  • 第二位玩家的初始分数

按以下格式打印输出:

Game: {GameName}
Player: {Username}, Score: {Score}
Player: {Username}, Score: {Score}
Total Players: {TotalPlayers}

例如,如果输入是 BattleArena、DragonSlayer、1500、ShadowNinja 和 2200,输出应为:

Game: BattleArena
Player: DragonSlayer, Score: 1500
Player: ShadowNinja, Score: 2200
Total Players: 2

仔细想想哪些数据应基于实例(每位玩家各不相同),哪些数据应是静态的(由所有玩家共享)。游戏名称和玩家总数描述的是整个会话,而用户名和分数则是每位玩家独有的。

亲手试试

using System;

namespace GameSession
{
    class Program
    {
        public static void Main(string[] args)
        {
            // 读取输入
            string gameName = Console.ReadLine();
            string username1 = Console.ReadLine();
            int score1 = Convert.ToInt32(Console.ReadLine());
            string username2 = Console.ReadLine();
            int score2 = Convert.ToInt32(Console.ReadLine());

            // TODO: 使用静态方法设置游戏名称

            // TODO: 使用输入数据创建两个 Player 对象

            // TODO: 按要求的格式打印输出
            // Game: {GameName}
            // Player: {Username}, Score: {Score}
            // Player: {Username}, Score: {Score}
            // Total Players: {TotalPlayers}
        }
    }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C# 在线编译器