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 类只读,静态构造改一次

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

相关推荐
IT乐手1 分钟前
Android 写本地日志工具类
android·java
汤米粥11 分钟前
Python调用百度搜索触发安全验证
开发语言·python
阿维的博客日记16 分钟前
spring里面的@RequestParam什么意思
java·后端·spring
laowangpython17 分钟前
昆仑通态 Mcgs Pro软件安装步骤(附安装包)Mcgs Pro 3.3.6 下载安装教程(保姆级)
java·服务器·数据库·其他
影寂ldy19 分钟前
C# 五大加密算法全套实战(AES/DES对称、RSA非对称、MD5/SHA256哈希)
开发语言·c#·哈希算法
互联网底层民工30 分钟前
异步 / 多线程并发(高频八股 · 详解版)
c#
罗超驿1 小时前
6.Java LinkedList深度解析:从链表原理到源码实践
java·开发语言·链表
2501_948106911 小时前
计算机毕业设计之jsp物业管理系统
java·大数据·开发语言·汽车·课程设计
黑taoA1 小时前
深度解析:Maven核心命令(clean、compile、package、install)与IDEA多模块项目避坑指南
java·maven·intellij-idea
TDengine (老段)1 小时前
TDengine 索引使用指南 — 何时建、怎么建、怎么用
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据