C# 静态成员 vs 非静态成员(调用规则+内存特点)+只读和常量 const常量 / readonly / static readonly 三者终极区别

一、核心本质区别(必考简答题)

1. 非静态成员(实例成员)

归属:对象(实例)

每 new 一个对象,就会产生独立的一份数据,对象之间互不干扰。

包含:非静态字段、非静态属性、非静态方法

2. 静态成员(static)

归属:类

全局只有唯一一份数据所有对象共享同一份静态数据

无论 new 多少个对象,静态成员永远只有一份

包含:静态字段、静态属性、静态方法


二、调用规则(超级重点,考试必坑)

1. 非静态成员调用

必须通过 对象名 调用

复制代码
People p1 = new People();
p1.F1();     // 非静态方法
p1.Id = 1;   // 非静态属性

2. 静态成员调用

必须通过 类名 调用(不推荐对象调用,规范写法)

复制代码
People.Age = 10; // 静态属性
People.F2();     // 静态方法

三、互相访问权限(死规则,必须背死)

1. 非静态方法【可以随便访问】静态成员

非静态方法中,可以直接使用静态属性、静态方法

原因:类静态数据全局常驻,对象实例可以读取类的数据

复制代码
public void F1()
{
    Age = 10;   // 直接访问静态属性
    F2();       // 直接访问静态方法
}

2. 静态方法【不能直接访问】非静态成员

静态方法中,不允许直接调用非静态属性/方法

原因:静态属于类,对象可能还没创建,没有实例数据

如果一定要用:必须手动 new 对象调用

复制代码
public static void F2()
{
    // 错误:直接使用非静态成员
    // Id = 1;  
    // F1();

    // 正确:new 对象后使用
    People p = new People();
    p.Id = 1;
    p.F1();
}

四、属性赋值死循环坑(你代码重点易错点)

错误写法(致命报错)

复制代码
set
{
    Id = value; // 死循环!!
}

原因:Id=value 是属性赋值,会重复触发set访问器,无限递归死循环

正确写法

复制代码
set
{
    Console.WriteLine("ssssssssss");
    id = value; // 给私有字段赋值,不触发set
}

口诀:属性set内部,只能给字段赋值,不能给属性赋值


五、静态/非静态 数据独立性代码演示

非静态属性:每个对象独立数据

复制代码
People p1 = new People();
p1.AddNum(); // p1.Num = 1

People p2 = new People();
p2.AddNum(); // p2.Num = 1

// 输出都是1,互不影响
Console.WriteLine(p1.GetNum()); 
Console.WriteLine(p2.GetNum());

非静态:一人一份,各自独立

如果是静态属性:所有对象共享一份数据

p1修改静态值 → p2读取到的也是修改后的值

静态:一改全改,全局共享


六、终极对比总表(默写满分)

对比维度 非静态(实例)成员 静态(static)成员
归属 属于对象 属于类
调用方式 对象名.成员 类名.成员
数据存储 每个对象独立一份数据 全局唯一一份,所有对象共享
访问权限 可直接访问静态成员 不可直接访问非静态,需new对象
创建时机 new对象后产生 类加载时就存在

七、考前终极口诀

  • 静态归类不归对象,全局共享只一份

  • 非静归对象,每个实例独自享

  • 非静可直接用静态,静态想用非静必须new

  • 属性set赋值给字段,千万别写属性死循环


八、简答题标准答案

1. 静态成员和非静态成员的区别?

静态成员属于类,全局唯一、所有对象共享一份数据,通过类名调用;非静态成员属于对象,每个对象拥有独立数据,通过对象调用。非静态方法可以直接访问静态成员,静态方法不能直接访问非静态成员,需要实例化对象才可访问。

const常量 / readonly / static readonly 三者终极区别

一、三种只读修饰符 代码对应定义

复制代码
// 1. 普通只读(实例只读)
public readonly int a = 10;

// 2. 静态只读
public static readonly int b = 20;

// 3. 常量
public const int c = 30;

二、逐条语法规则(必考)

1. const 常量

  • 默认自带 static,属于类

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

  • 任何位置都不能修改(构造函数也不能改)

  • 调用方式:类名.常量名

  • 编译阶段直接固定值,不可变动

2. readonly 实例只读

  • 属于对象(实例)

  • 可以定义时赋值

  • 只能在【无参/有参实例构造函数】中修改一次

  • 构造函数执行完毕后,彻底禁止修改

  • 不能在静态构造函数修改

3. static readonly 静态只读

  • 属于

  • 可以定义时赋值

  • 只能在【静态构造函数】中修改

  • 绝对不能在普通实例构造函数修改

  • 全局唯一、所有对象共享


三、你代码中的执行逻辑精讲

复制代码
public readonly int a = 10;
public static readonly int b = 20;
public const int c = 30;

// 实例构造
public People()
{
    a =20; // 正确:实例只读只能在这里改
    // b = 30; // 报错!静态只读不能在实例构造修改
}

// 静态构造
static People()
{
    b = 40; // 正确:静态只读只能在这里改
}

执行顺序与结果

  1. 程序触发类使用 → 静态构造函数先执行 → b=40

  2. new 对象 → 实例构造执行 → a=20

  3. 输出结果: 40---------------- 静态构造函数只能被调用一次... 20++++++++++++ 40 30


四、修改权限禁区(超级易错)

类型 定义赋值 实例构造修改 静态构造修改 程序运行中修改
const 常量 必须赋值 ❌ 不能改 ❌ 不能改 ❌ 完全不能改
readonly 实例只读 可选 ✅ 可改一次 ❌ 不能改 ❌ 不能改
static readonly 静态只读 可选 ❌ 不能改 ✅ 可改一次 ❌ 不能改

五、调用方式区别

  • readonly :对象调用 p1.a

  • static readonly :类名调用 People.b

  • const :类名调用 People.c


六、三者终极区别(简答题满分)

1. const 常量

编译期常量,默认静态,定义时必须赋值,任何位置不可修改,性能最高。

2. readonly 实例只读字段

属于对象,仅可在实例构造函数中赋值修改一次,运行期只读,不同对象可以有不同数值。

3. static readonly 静态只读字段

属于类,仅可在静态构造函数中赋值修改一次,全局所有对象共享同一个值。


七、满分背诵口诀

  • const 常量编译定,全程谁都不能动

  • readonly 对象只读,实例构造唯一动

  • static readonly 类只读,静态构造改一次

  • 构造结束全锁死,运行期间不许动

相关推荐
zhangfeng11331 小时前
超算中心 高性能计算 slurm的linux版本 centos7,如何安装docker,如何安装torch2.4
linux·运维·服务器·开发语言·人工智能·机器学习·docker
java1234_小锋1 小时前
LangChain4j 开发Java Agent智能体- 整合SpringBoot4
java·开发语言·langchain4j
basketball6161 小时前
C++进阶:3. unique_ptr 现代C++内存管理的基石
java·jvm·c++
我不是懒洋洋1 小时前
从零实现一个Redis客户端:RESP协议与网络编程
开发语言·c++
zzqssliu1 小时前
跨境代购系统的物流和通知模块重构思考:从设计模式到生产落地
java·设计模式·重构
小小码农Come on1 小时前
Qt::WA_StyledBackground属性的作用
开发语言·qt
appearappear1 小时前
一句sql 根据明细数据状态,精确更新一个主单主状态
java
许彰午1 小时前
04_Java数组操作全解
java·开发语言·python
AIGS0011 小时前
生产运营三大瓶颈,工业AI怎么破局?
java·人工智能·人工智能ai大模型应用