C#零基础通关第六篇:吃透静态、常量与只读,分清静态与实例的本质差异

上一篇我们彻底掌握了面向对象三大核心特性:封装、继承、多态,学会了通过类封装数据、通过继承复用代码、通过多态实现灵活拓展。

我们之前写的所有字段、属性、方法,都属于实例成员,必须实例化对象后才能调用。但在实际项目开发中,有很多通用工具方法、全局共享数据、固定不变的常量,根本不需要反复 new 对象。

这就引出了C#开发中最容易混淆、面试必考、项目必用 的核心知识点:静态成员、静态类、const常量、readonly只读

很多新手写代码多年,依然分不清:静态和实例到底有什么区别?const和readonly看着一样为什么不能混用?什么时候用静态类、什么时候用普通类?

本篇从零拆解所有核心概念,搭配可落地实战代码,彻底扫清这块知识盲区,补齐面向对象的最后一块核心短板。

一、前置核心:实例 vs 静态(本质区别)

在学习具体语法前,我们先搞懂最核心的底层逻辑,这是所有知识点的基础。

1. 实例成员(之前所学全部内容)

我们之前写的普通属性、普通方法,都属于实例成员。

  • 归属 :归属于 对象,不归属于类

  • 调用方式 :必须 new 类名()实例化对象后调用

  • 内存特点:每 new 一个对象,就会开辟一块独立内存,对象之间数据互不干扰

  • 场景:每个对象独有、独立的数据和行为(学生姓名、年龄、学习行为)

2. 静态成员(本篇核心)

static 修饰的成员,统称为静态成员。

  • 归属 :归属于 ,不归属于任何对象

  • 调用方式 :直接 类名.成员名 调用,无需 new 对象

  • 内存特点:全局唯一,整个程序运行期间只开辟一块内存,所有对象共享同一份数据

  • 场景:全局共享数据、通用工具方法、统计计数

3. 一句话总结

实例成员:每个对象各有一份,互不干扰;静态成员:整个类只有一份,全员共享。

二、静态成员:静态字段与静态方法

1. 静态字段(static 字段)

普通字段是对象独有,静态字段是类共享,适合存储全局公共数据、统计数据。我们用「学生人数统计」实战演示,这是静态字段最经典的应用场景。

csharp 复制代码
using System;

class Student
{
    // 实例属性:每个学生独有
    public string Name { get; set; }
    public int Age { get; set; }

    // 静态字段:全局共享,统计学生总人数
    public static int TotalCount = 0;

    // 构造函数:每创建一个学生,人数+1
    public Student(string name, int age)
    {
        Name = name;
        Age = age;
        // 所有对象共享同一个静态字段
        TotalCount++;
    }
}

class Program
{
    static void Main()
    {
        // 创建多个学生对象
        Student s1 = new Student("张三", 18);
        Student s2 = new Student("李四", 19);
        Student s3 = new Student("王五", 18);

        // 直接通过类名调用静态字段
        Console.WriteLine($"当前学生总人数:{Student.TotalCount}");
    }
}

运行结果:当前学生总人数:3

可以清晰看出:多个对象共用同一个静态字段,实现了全局统计效果,这是实例字段完全做不到的。

2. 静态方法(static 方法)

被 static 修饰的方法,无需实例化,直接类名调用,核心场景:通用工具方法(数学计算、格式转换、数据校验)。

⚠️ 核心规则(必考)

  • 静态方法中 只能直接访问静态成员

  • 静态方法中 不能直接访问实例成员(必须实例化对象后才能访问)

  • 实例方法中 可以直接访问静态成员

csharp 复制代码
using System;

// 通用工具类
class MathTool
{
    // 静态方法:计算两数之和
    public static int GetSum(int a, int b)
    {
        return a + b;
    }

    // 静态方法:计算平方
    public static int GetSquare(int num)
    {
        return num * num;
    }
}

class Program
{
    static void Main()
    {
        // 无需new对象,直接类名调用
        Console.WriteLine($"10+20={MathTool.GetSum(10, 20)}");
        Console.WriteLine($"10的平方={MathTool.GetSquare(10)}");
    }
}

三、静态构造函数(特殊核心语法)

静态构造函数是新手最容易懵的知识点,它和实例构造函数完全不同,专门用来初始化静态成员

1. 静态构造函数特性(必记)

  • 无访问修饰符、无参数

  • 一个类 只能有一个 静态构造函数

  • 程序运行中 只会执行一次,在第一次使用类时自动触发

  • 优先级高于实例构造函数,优先执行

2. 实战演示

csharp 复制代码
using System;

class Test
{
    public static string Msg;

    // 静态构造函数:初始化静态数据
    static Test()
    {
        Msg = "静态数据初始化完成";
        Console.WriteLine("静态构造函数执行!");
    }

    // 实例构造函数
    public Test()
    {
        Console.WriteLine("实例构造函数执行!");
    }
}

class Program
{
    static void Main()
    {
        // 第一次使用类,触发静态构造函数
        Console.WriteLine(Test.Msg);
        // 多次实例化,静态构造函数不再执行
        Test t1 = new Test();
        Test t2 = new Test();
    }
}

执行顺序:静态构造函数 → 输出信息 → 两次实例构造函数

四、静态类(static class)

被 static 修饰的类,即为静态类,项目中专门用来写工具类、帮助类

1. 静态类核心特性

  • 只能包含静态成员,不能有实例成员

  • 禁止实例化,不能 new 对象

  • 程序加载时自动初始化,全局可调用

2. 实战标准工具类(项目常用模板)

csharp 复制代码
using System;

// 静态工具类:全部为通用静态方法
static class StringTool
{
    // 字符串判空
    public static bool IsEmpty(string str)
    {
        return string.IsNullOrEmpty(str);
    }

    // 反转字符串
    public static string ReverseStr(string str)
    {
        char[] chars = str.ToCharArray();
        Array.Reverse(chars);
        return new string(chars);
    }
}

class Program
{
    static void Main()
    {
        string test = "C#零基础";
        Console.WriteLine(StringTool.IsEmpty(test));
        Console.WriteLine(StringTool.ReverseStr(test));
    }
}

项目中所有工具方法(数据校验、格式处理、算法封装),统一放在静态类中,是企业开发规范。

五、常量 const 与 只读 readonly(高频混淆点)

很多新手分不清 const 和 readonly,二者都是「只读不可修改」,但底层机制、使用场景完全不同,是面试和项目的高频考点。

1. const 常量(编译时常量)

  • 本质:编译期常量,程序编译时就确定值,不可修改

  • 修饰 :默认是 静态,无需加 static

  • 赋值:必须在定义时直接赋值,不能延迟赋值

  • 场景:全局固定不变的数值(圆周率、版本号、状态码)

2. readonly 只读(运行时常量)

  • 本质:运行时常量,程序运行时确定值,赋值后不可修改

  • 修饰:属于实例成员(可搭配static变为静态只读)

  • 赋值:可以定义时赋值,也可以在构造函数中赋值

  • 场景:对象初始化时确定、后续永不修改的数据

3. 代码对比实战

csharp 复制代码
using System;

class Config
{
    // const 编译时常量:定义必须赋值,全局静态只读
    public const double PI = 3.1415926;

    // readonly 实例只读字段:可在构造函数赋值
    public readonly string Version;

    public Config()
    {
        // 允许在构造函数赋值
        Version = "V1.0.0";
        // 报错!const 不能在构造函数赋值
        // PI = 3.14;
    }
}

class Program
{
    static void Main()
    {
        // const 直接类名调用
        Console.WriteLine(Config.PI);

        Config cfg = new Config();
        Console.WriteLine(cfg.Version);

        // 报错!只读/常量禁止二次赋值
        // cfg.Version = "V2.0";
        // Config.PI = 3.15;
    }
}

4. 核心取舍规则

  • 固定死的数值(永不改变):用 const

  • 运行时确定、后续不变的数值:用 readonly

六、全文整合实战案例

整合静态类、静态成员、常量、只读,实现一个简易项目配置工具,完全贴合企业开发场景:

csharp 复制代码
using System;

// 全局静态配置工具类
static class AppConfig
{
    // 常量:固定项目版本
    public const string ProjectName = "C#零基础教程";

    // 静态只读:运行时初始化
    public static readonly string RunTime;

    // 静态构造函数:初始化静态数据
    static AppConfig()
    {
        RunTime = DateTime.Now.ToString("yyyy-MM-dd");
    }

    // 静态工具方法:打印配置信息
    public static void PrintConfig()
    {
        Console.WriteLine($"项目名称:{ProjectName}");
        Console.WriteLine($"启动时间:{RunTime}");
    }
}

class Program
{
    static void Main()
    {
        // 直接调用静态类方法
        AppConfig.PrintConfig();
    }
}

七、新手高频易错坑点(必避)

  • 静态方法不能调用实例成员:静态属于类,实例属于对象,生命周期不同,禁止直接调用;

  • 静态构造函数只会执行一次:无论实例化多少次对象,静态构造函数仅首次加载类时执行;

  • 静态类不能实例化:静态类专为工具方法设计,不需要 new 对象;

  • const必须当场赋值:编译时常量不支持构造函数延迟赋值,readonly支持;

  • 静态数据全局共享:多对象修改同一个静态字段,会互相影响,慎用静态存储可变数据。

八、全文核心总结

  1. 实例成员:归属于对象,每个对象独立,必须 new 调用;

  2. 静态成员:归属于类,全局共享,直接类名调用,适合工具方法、全局统计;

  3. 静态类:专门存放通用工具方法,禁止实例化,是项目开发标准工具类写法;

  4. const常量:编译期固定值,全局静态,适合固定参数;

  5. readonly只读:运行时赋值,赋值后不可修改,适合动态初始化的固定数据。

静态与实例的区分、常量与只读的使用,是后续学习框架开发、工具封装、多线程的基础,务必吃透。

下期预告

下一篇我们将精讲 C# 委托与事件,这是C#独有的核心高级特性,是Unity游戏开发、窗体事件编程、框架解耦的核心关键,零基础也能轻松听懂!

相关推荐
Scout-leaf1 天前
C#摸鱼实录——IoC与DI案例详解
c#
咕白m6251 天前
使用 C# 在 Excel 中应用多种字体样式
后端·c#
Artech2 天前
[MAF预定义的AIContextProvider-02]AgentSkillsProvider——将Agent Skills引入MAF
ai·c#·agent·agent skills·maf
LDR0062 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术2 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript
码云数智-园园2 天前
C++20 Modules 模块详解
java·开发语言·spring
swordbob2 天前
NIO的channel中什么是 fd(File Descriptor,文件描述符)
java·开发语言·nio
源分享2 天前
Java线程同步的多种实现方法(非常详细)
java·开发语言·jvm
Luminous.2 天前
C语言--day30
c语言·开发语言
何以解忧,唯有..2 天前
Go语言循环语句详解:for、range与循环控制
开发语言·算法·golang