C#核心学习(六)面向对象--封装(5)静态成员及静态构造函数和静态类 以及和常量的区别
目录
一、什么是静态的?什么是常量?
1. 静态(Static)
2. 常量(const)
二、类中的静态成员有什么用?
1. 共享数据
2. 工具方法与全局配置
3. 单例模式
三、静态类和静态成员方法的介绍
1. 静态类(Static Class)
2. 静态构造函数(Static Constructor)
3. 静态方法的限制
四、对比总结
1. 静态成员 vs 常量(const)
2. 静态类 vs 普通类
3. 使用场景
注意事项
前言:代码中的“共享经济”与“不变法则”
有没有想过,如何让一个类的所有实例共享同一份数据?或者怎样创建一种无需实例化就能调用的“工具包”方法?
在C#的世界里,静态成员就像魔法般的全局变量,而常量则是刻在代码石碑上的永恒法则。它们一个灵活善变(但需谨慎),一个坚守初心(绝不妥协)。
本文将揭秘静态类的“禁欲系”设计、静态构造函数的幕后初始化大法,并带你理清静态成员与常量的爱恨纠葛——从此告别重复代码,让你的程序优雅如诗!
一、什么是静态的?什么是常量?
1. 静态(Static)
静态是C#中用于描述类级别成员的关键字。静态成员(如静态字段、方法、属性)属于类本身而非类的实例,所有实例共享同一份静态成员。
- 内存分配:静态成员在程序启动时分配内存,生命周期与应用程序一致。
- 访问方式:直接通过类名访问,无需实例化对象。
记住!!!
程序是不能无中生有的
我们要使用的对象 变量 函数 都是要在内存中分配空间的
之所以要实例化对象 目的就是要分配内存空间,在程序中 产生一个抽象的对象静态成员的特点
程序开始运行时 就会分配内存空间 所以我们可以直接使用
静态成员和程序同生共死
只要使用了他 直到程序结束时 内存空间才会被释放
所以每个静态成员都有属于自己的唯一一个小房间
这让静态成员便有了唯一性
在任何地方使用 都是使用小房间里面的内容 修改的也是房间里面的内容
2. 常量(const)
常量是通过const
关键字定义的不可修改的编译时常量。
- 内存分配:值在编译时确定并嵌入到IL代码中。
- 不可变性:必须在声明时赋值,且只能为基本类型(如
int
,string
)或null
。
// 静态字段 vs 常量
public class Config {
public static string Environment = "Production"; // 静态字段(可修改)
public const int MaxRetryCount = 3; // 常量(不可修改)
}
const (常量)可以理解为特殊的静态static
相同点:
他们都可以通过类名点出使用
不同点
1.const 必须初始化,不能修改 static 没有这个限制
2.const 只能修饰变量,static可以修饰很多
3.const一定是写在访问修饰符后面的,static没有这个要求
二、类中的静态成员有什么用?
1. 共享数据
静态成员用于存储所有实例共享的数据。例如,统计类的实例总数:
public class User {
public static int UserCount = 0; // 所有实例共享
public User() {
UserCount++;
}
}
Console.WriteLine(User.UserCount); // 直接通过类访问
2. 工具方法与全局配置
将无需实例化的工具方法或全局配置定义为静态成员:
public class MathUtils {
public static double PI = 3.1415926;
public static int Add(int a, int b) => a + b;
}
Console.WriteLine(MathUtils.Add(2, 3)); // 直接调用静态方法
3. 单例模式
通过静态成员实现单例(确保类只有一个实例):
public class Singleton {
private static Singleton _instance;
public static Singleton Instance => _instance ??= new Singleton();
private Singleton() { }
}
三、静态类和静态成员方法的介绍
1. 静态类(Static Class)
- 定义:用
static
修饰的类,不能实例化,只能包含静态成员。 - 用途:封装工具类或扩展方法容器。
public static class StringExtensions {
public static string ToTitleCase(this string input) {
return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(input);
}
}
string name = "john doe";
Console.WriteLine(name.ToTitleCase()); // 输出 "John Doe"
注意:直接类名然后点出来使用 里面的方法
2. 静态构造函数(Static Constructor)
- 作用:初始化静态字段或执行一次性的静态初始化逻辑。
- 调用时机:在类首次被访问(如创建实例、调用静态方法)时自动执行。
注:这里的创造实例是指的是点出内部已经给你创造好的实例。你自己是无法new的。
看如下代码:
public class Singleton {
// 静态成员管理唯一实例
private static Singleton _instance;
public static Singleton Instance => _instance ??= new Singleton();
// 私有构造函数,禁止外部 new
private Singleton() { }
}
// 正确!通过静态属性访问唯一实例
var instance = Singleton.Instance;
这份代码是静态构造函数的一个实际应用:
这段代码定义了一个 Logger
类,其核心功能是初始化日志文件的存储目录。通过静态成员和静态构造函数的设计,确保日志目录在程序运行期间只创建一次,且无需手动初始化。
public class Logger {
public static string LogDirectory;
static Logger() {
LogDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
Directory.CreateDirectory(LogDirectory);
}
}
注意:这个主要是用来初始化,做一些配置什么的
3. 静态方法的限制
- 不能访问实例成员(非静态字段、方法),只能访问其他静态成员。
- 不能使用
this
关键字。
四、对比总结
1. 静态成员 vs 常量(const)
特性 | 静态成员 | 常量(const) |
---|---|---|
内存分配 | 运行时分配 | 编译时嵌入到IL代码 |
可修改性 | 可修改(除非是readonly ) | 不可修改 |
类型限制 | 无限制 | 仅支持基本类型或null |
初始化时机 | 静态构造函数或声明时 | 必须在声明时赋值 |
2. 静态类 vs 普通类
特性 | 静态类 | 普通类 |
---|---|---|
实例化 | 不可实例化 | 可以实例化 |
成员类型 | 仅包含静态成员 | 可包含静态和实例成员 |
继承 | 不能继承或被继承 | 支持继承 |
3. 使用场景
- 静态成员:共享数据、工具方法、全局配置。
- 静态类:工具类、扩展方法容器、单例模式。
- 常量:固定不变的值(如数学常数、配置标志)。
注意事项
- 避免过度使用静态成员:可能导致代码耦合度高、难以测试。
- 线程安全问题:静态成员在多线程环境下需加锁(如
lock
)。- 常量的限制:无法在运行时动态赋值(如从配置文件读取)。
- 静态构造函数的性能:避免在静态构造函数中执行耗时操作。
通过合理使用静态成员和常量,可以显著提升代码的模块化和执行效率,但需谨慎平衡其适用场景!