静态(static)是C#中一个重要的关键字,它可以应用于类、方法、属性和字段。
静态类
静态类的特点:
- 不能实例化
- 只能包含静态成员
- 密封的(sealed),不能被继承
应用场景:
- 工具类/辅助类
- 数学计算类:如Math类
- 扩展方法、全局访问等
扩展方法
扩展方法必须写在非泛型的静态类中
对int类型进行扩展,添加一个Divide方法,返回double类型
this 后面跟类型和参数名称,为要进行扩展的类
public static class ExtendMethod
{
public static double Divide(this int a, int b)
{
return a*1.0 / b;
}
}
使用
静态类
除扩展方法外,其他类中,除非特殊需要一般不直接写为静态类,因为静态类中的,方法、属性、成员必须是静态的。
public static class StringHelper
{
public static string Reverse(string input)
{
char[] charArray = input.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
}
// 使用
var result = StringHelper.Reverse("hello");
静态方法
- 不依赖于实例对象
- 单例模式的实力获取方法
在类中添加一个生成单例的方法,当然也运行通过new的方式创建,此时非单例
public class Logger
{
private static Logger _instance;
private static object _lock = new object();
public static Logger GetInstance()
{
lock (_lock)
{
if (_instance == null)
{
_instance = new Logger();
}
return _instance;
}
}
// 实例方法
public void Log(string message)
{
Console.WriteLine(message);
}
}
使用
static void Main(string[] args)
{
Logger logger = Logger.GetInstance();
logger.Log("Test message");
Console.ReadLine();
}
静态属性
- 共享数据,全局配置
- 资源计数
- 单例实例访问
private static object _syncObj = new object();
private static KvPLC _instance = null;
public static KvPLC KvInstance //单例对象
{
get
{
lock (_syncObj)
{
if (_instance == null)
{
_instance = new KvPLC();
}
}
return _instance;
}
}
静态字段
- 共享数据、缓存常用数据
- 计数器
- 只读常量(通常与const或readonly一起使用)
统计User类的用户数量
public class User
{
private static int _userCount = 0;
public User()
{
_userCount++;
}
public static int TotalUserCount=>_userCount;
}
使用
static void Main(string[] args)
{
var user1 = new User();
var user2 = new User();
//总用户数:2
Console.WriteLine($"总用户数:{User.TotalUserCount}");
Console.ReadLine();
}
优点:
- 无需实例化即可使用, 全局可访问(需谨慎使用)
缺点:
-
可能导致代码紧耦合,难以进行单元测试
-
过度使用可能导致"上帝对象"问题
-
线程安全问题(需要特别注意同步)
静态属性和静态字段
访问控制
静态字段
- 直接暴露数据,无访问控制逻辑
- 若为public,外部可直接修改值,风险较高
public static class Counter {
public static int Count; // 直接暴露
}
// 外部可直接修改
Counter.Count = 100; // 无任何验证逻辑
- 静态属性
- 通过get/set控制访问
- 可添加验证逻辑、延迟加载、线程同步等
验证逻辑
public static class Counter {
private static int _count;
public static int Count {
get => _count;
set {
if (value >= 0) // 添加验证
_count = value;
}
}
}
Counter.Count = -5; // 赋值无效,值不会被修改
延迟加载
public static class LazyData {
private static Data _data;
public static Data Data {
get {
if (_data == null)
_data = LoadData();
return _data;
}
}
private static Data LoadData() { /*...*/ }
}
线程安全
public static class ThreadSafeCounter {
private static int _count;
private static object _lock = new();
public static int Count {
get { lock(_lock) return _count; }
set { lock(_lock) _count = value; }
}
}
初始化方式
静态字段
- 支持直接初始化或通过静态构造函数
- 可声明为readonly(只读)
public static class Constants {
public static readonly int MaxRetries = 3; // 运行时初始化
public const string AppName = "MyApp"; // 编译时常量
}
静态属性
- 初始化需通过访问器或静态构造函数
- 不可直接使用readonly,但可通过私有set实现只读
public static class Config {
public static string Environment { get; } = "Production"; // 只读属性
public static int Timeout { get; private set; } = 30; // 限制外部修改
}
总结
-
简单数据存储 → 优先使用private static field + public static property
-
需要控制访问或扩展逻辑 → 必须使用静态属性
-
常量数据 → 使用public const或public static readonly字段
-
线程共享数据 → 通过属性添加同步机制