Administrator
发布于 2025-10-12 / 3 阅读
0
0

C#中static关键字的完整指南

static关键字是C#中非常重要的概念,用于创建属于类型本身而不是类型实例的成员。

1. static关键字的基本概念

什么是static?

加上 static 的成员不再属于某个对象实例,而是直接属于类本身; 无论创建多少个实例,静态成员只有一份,通过类名即可访问。

  • static成员属于类型本身,而不是类型的实例

  • 在程序运行期间,static成员只有一份副本

  • 不需要创建对象实例即可访问static成员

  • static成员在类型第一次被使用时初始化

2. 静态类(Static Classes)

静态类的特点:

  • 不能实例化(不能使用new创建对象)

  • 只能包含静态成员

  • 是密封的(不能被继承)

using System;
​
// 静态类定义
public static class MathUtilities
{
    // 静态字段
    public static readonly double PI = 3.14159;
    
    // 静态方法
    public static double CalculateCircleArea(double radius)
    {
        return PI * radius * radius;
    }
    
    public static int Add(int a, int b)
    {
        return a + b;
    }
    
    public static bool IsEven(int number)
    {
        return number % 2 == 0;
    }
}
​
class Program
{
    static void Main()
    {
        // 直接通过类名访问静态成员
        double area = MathUtilities.CalculateCircleArea(5.0);
        int sum = MathUtilities.Add(10, 20);
        bool isEven = MathUtilities.IsEven(15);
        
        Console.WriteLine($"圆面积: {area}");
        Console.WriteLine($"和: {sum}");
        Console.WriteLine($"15是偶数: {isEven}");
        
        // 编译错误:不能创建静态类的实例
        // MathUtilities utils = new MathUtilities(); // 错误!
    }
}

3. 静态字段(Static Fields)

静态字段的特点:

  • 所有实例共享同一个字段

  • 在类第一次被使用时初始化

using System;
​
public class Counter
{
    // 实例字段 - 每个对象有自己的副本
    public int InstanceCount = 0;
    
    // 静态字段 - 所有对象共享同一个副本
    public static int StaticCount = 0;
    
    public Counter()
    {
        InstanceCount++;
        StaticCount++;
    }
    
    public void DisplayCounts()
    {
        Console.WriteLine($"实例计数: {InstanceCount}, 静态计数: {StaticCount}");
    }
}
​
class Program
{
    static void Main()
    {
        Counter c1 = new Counter();
        c1.DisplayCounts(); // 实例计数: 1, 静态计数: 1
        
        Counter c2 = new Counter();
        c2.DisplayCounts(); // 实例计数: 1, 静态计数: 2
        
        Counter c3 = new Counter();
        c3.DisplayCounts(); // 实例计数: 1, 静态计数: 3
        
        // 直接访问静态字段
        Console.WriteLine($"总计数器: {Counter.StaticCount}"); // 输出: 3
    }
}

4. 静态方法(Static Methods)

静态方法的特点:

  • 属于类本身,不属于任何实例

  • 只能访问静态成员,不能直接访问实例成员

  • 不需要创建对象即可调用

using System;
​
public class StringHelper
{
    // 实例方法 - 需要对象实例
    public string InstanceToUpper(string input)
    {
        return input.ToUpper();
    }
    
    // 静态方法 - 直接通过类名调用
    public static string StaticToUpper(string input)
    {
        return input.ToUpper();
    }
    
    // 静态方法只能访问静态成员
    private static string _prefix = "STATIC: ";
    
    public static string FormatMessage(string message)
    {
        return _prefix + message.ToUpper();
        // 编译错误:不能访问实例成员
        // return InstanceToUpper(message); // 错误!
    }
}
​
class Program
{
    static void Main()
    {
        // 调用静态方法 - 不需要创建对象
        string result1 = StringHelper.StaticToUpper("hello");
        string result2 = StringHelper.FormatMessage("world");
        
        Console.WriteLine(result1); // 输出: HELLO
        Console.WriteLine(result2); // 输出: STATIC: WORLD
        
        // 调用实例方法 - 需要创建对象
        StringHelper helper = new StringHelper();
        string result3 = helper.InstanceToUpper("hello");
        Console.WriteLine(result3); // 输出: HELLO
    }
}

5. 静态属性(Static Properties)

using System;
using System.Collections.Generic;
​
public class AppSettings
{
    // 静态属性
    public static string AppName { get; set; } = "MyApplication";
    
    public static string Version { get; } = "1.0.0"; // 只读静态属性
    
    // 带有私有字段的静态属性
    private static int _userCount = 0;
    public static int UserCount
    {
        get { return _userCount; }
        private set { _userCount = value; } // 私有setter
    }
    
    public static void AddUser()
    {
        UserCount++;
    }
}
​
class Program
{
    static void Main()
    {
        // 访问静态属性
        Console.WriteLine($"应用名: {AppSettings.AppName}");
        Console.WriteLine($"版本: {AppSettings.Version}");
        Console.WriteLine($"用户数: {AppSettings.UserCount}");
        
        AppSettings.AddUser();
        AppSettings.AddUser();
        
        Console.WriteLine($"更新后用户数: {AppSettings.UserCount}");
        
        // 修改静态属性
        AppSettings.AppName = "AwesomeApp";
        Console.WriteLine($"新应用名: {AppSettings.AppName}");
    }
}

6. 静态构造函数(Static Constructors)

静态构造函数的特点:

  • 在类第一次被使用前自动调用

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

  • 不能有访问修饰符

  • 不能有参数

using System;
​
public class DatabaseManager
{
    // 静态字段
    private static readonly string ConnectionString;
    private static readonly DateTime InitializeTime;
    
    // 静态构造函数
    static DatabaseManager()
    {
        InitializeTime = DateTime.Now;
        ConnectionString = "Server=localhost;Database=MyApp;Trusted_Connection=true;";
        
        Console.WriteLine($"静态构造函数被调用,初始化时间: {InitializeTime}");
        Console.WriteLine("数据库连接已配置");
    }
    
    // 静态方法
    public static void ExecuteQuery(string query)
    {
        Console.WriteLine($"执行查询: {query}");
        Console.WriteLine($"使用连接字符串: {ConnectionString}");
    }
    
    public static void ShowInfo()
    {
        Console.WriteLine($"初始化时间: {InitializeTime}");
    }
}
​
class Program
{
    static void Main()
    {
        Console.WriteLine("程序开始");
        
        // 第一次使用类,触发静态构造函数
        DatabaseManager.ExecuteQuery("SELECT * FROM Users");
        
        // 不会再次调用静态构造函数
        DatabaseManager.ShowInfo();
    }
}

7. 静态只读字段(Static Readonly Fields)

using System;
​
public class Constants
{
    // 编译时常量
    public const double PI = 3.14159;
    
    // 运行时常量(静态只读字段)
    public static readonly DateTime BuildTime;
    public static readonly string Version;
    
    // 静态构造函数中初始化
    static Constants()
    {
        BuildTime = DateTime.Now;
        Version = "2.1.0";
    }
    
    // 复杂类型的静态只读字段
    public static readonly List<string> SupportedLanguages = new List<string>
    {
        "C#", "Java", "Python", "JavaScript"
    };
}
​
class Program
{
    static void Main()
    {
        Console.WriteLine($"PI: {Constants.PI}");
        Console.WriteLine($"构建时间: {Constants.BuildTime}");
        Console.WriteLine($"版本: {Constants.Version}");
        
        Console.WriteLine("支持的语言:");
        foreach (string language in Constants.SupportedLanguages)
        {
            Console.WriteLine($" - {language}");
        }
        
        // 可以修改集合内容,但不能重新赋值
        Constants.SupportedLanguages.Add("Go");
        // Constants.SupportedLanguages = new List<string>(); // 错误!
    }
}

8. 实际应用场景

场景1:工具类(Utility Classes)

using System;
using System.Text;
​
public static class StringExtensions
{
    public static string Reverse(this string input)
    {
        char[] chars = input.ToCharArray();
        Array.Reverse(chars);
        return new string(chars);
    }
    
    public static bool IsPalindrome(this string input)
    {
        string cleaned = input.ToLower().Replace(" ", "");
        return cleaned == cleaned.Reverse();
    }
    
    public static string ToTitleCase(this string input)
    {
        if (string.IsNullOrEmpty(input))
            return input;
            
        string[] words = input.ToLower().Split(' ');
        StringBuilder result = new StringBuilder();
        
        foreach (string word in words)
        {
            if (word.Length > 0)
            {
                result.Append(char.ToUpper(word[0]) + word.Substring(1) + " ");
            }
        }
        
        return result.ToString().Trim();
    }
}
​
class Program
{
    static void Main()
    {
        string text = "hello world";
        
        Console.WriteLine($"原始: {text}");
        Console.WriteLine($"反转: {text.Reverse()}");
        Console.WriteLine($"标题格式: {text.ToTitleCase()}");
        Console.WriteLine($"'radar'是回文: {"radar".IsPalindrome()}");
        Console.WriteLine($"'hello'是回文: {"hello".IsPalindrome()}");
    }
}

场景2:单例模式(Singleton Pattern)

using System;
​
public class Logger
{
    // 静态实例
    private static Logger _instance;
    private static readonly object _lockObject = new object();
    
    // 私有构造函数防止外部实例化
    private Logger()
    {
        Console.WriteLine("Logger实例已创建");
    }
    
    // 静态属性获取单例实例
    public static Logger Instance
    {
        get
        {
            // 双重检查锁定
            if (_instance == null)
            {
                lock (_lockObject)
                {
                    if (_instance == null)
                    {
                        _instance = new Logger();
                    }
                }
            }
            return _instance;
        }
    }
    
    public void Log(string message)
    {
        Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}");
    }
}
​
class Program
{
    static void Main()
    {
        // 使用单例
        Logger logger1 = Logger.Instance;
        logger1.Log("第一条日志");
        
        Logger logger2 = Logger.Instance;
        logger2.Log("第二条日志");
        
        // 检查是否是同一个实例
        Console.WriteLine($"logger1 == logger2: {logger1 == logger2}"); // 输出: True
    }
}

场景3:缓存管理

using System;
using System.Collections.Generic;

public static class Cache
{
    private static readonly Dictionary<string, object> _cache = new Dictionary<string, object>();
    private static readonly object _lockObject = new object();
    
    public static void Set(string key, object value)
    {
        lock (_lockObject)
        {
            _cache[key] = value;
        }
    }
    
    public static T Get<T>(string key)
    {
        lock (_lockObject)
        {
            if (_cache.ContainsKey(key) && _cache[key] is T)
            {
                return (T)_cache[key];
            }
            return default(T);
        }
    }
    
    public static bool Contains(string key)
    {
        lock (_lockObject)
        {
            return _cache.ContainsKey(key);
        }
    }
    
    public static void Remove(string key)
    {
        lock (_lockObject)
        {
            _cache.Remove(key);
        }
    }
    
    public static void Clear()
    {
        lock (_lockObject)
        {
            _cache.Clear();
        }
    }
}

class Program
{
    static void Main()
    {
        // 使用静态缓存
        Cache.Set("UserName", "张三");
        Cache.Set("UserAge", 25);
        Cache.Set("LoginTime", DateTime.Now);
        
        string name = Cache.Get<string>("UserName");
        int age = Cache.Get<int>("UserAge");
        DateTime loginTime = Cache.Get<DateTime>("LoginTime");
        
        Console.WriteLine($"用户名: {name}");
        Console.WriteLine($"年龄: {age}");
        Console.WriteLine($"登录时间: {loginTime}");
        
        Console.WriteLine($"缓存中包含UserName: {Cache.Contains("UserName")}");
        
        Cache.Remove("UserAge");
        Console.WriteLine($"缓存中包含UserAge: {Cache.Contains("UserAge")}");
    }
}

9. 最佳实践和注意事项

最佳实践:

  1. 使用场景

    • 工具类和方法

    • 共享数据或状态

    • 单例模式

    • 常量定义

  2. 线程安全

public static class ThreadSafeExample
{
    private static int _counter = 0;
    private static readonly object _lockObject = new object();
    
    // 线程安全的方法
    public static void IncrementCounter()
    {
        lock (_lockObject)
        {
            _counter++;
        }
    }
    
    public static int GetCounter()
    {
        lock (_lockObject)
        {
            return _counter;
        }
    }
}
  1. 避免的问题

    • 过度使用静态成员可能导致紧耦合

    • 静态变量在整个应用程序生命周期中存在,可能占用内存

    • 测试困难(静态方法难以mock)

注意事项:

public class Example
{
    // 好的实践:工具方法设为静态
    public static bool IsValidEmail(string email)
    {
        return !string.IsNullOrEmpty(email) && email.Contains("@");
    }
    
    // 不好的实践:与对象状态相关的方法不应设为静态
    // public static string GetUserInfo() { } // 错误!
    
    // 好的实践:常量使用const或static readonly
    public const int MAX_USERS = 100;
    public static readonly DateTime StartupTime = DateTime.Now;
}

// 使用示例
class Program
{
    static void Main()
    {
        // 正确的使用
        bool isValid = Example.IsValidEmail("test@example.com");
        Console.WriteLine($"邮箱有效: {isValid}");
        
        // 访问常量
        Console.WriteLine($"最大用户数: {Example.MAX_USERS}");
        Console.WriteLine($"启动时间: {Example.StartupTime}");
    }
}

10. 总结

static关键字在C#中用于创建属于类型本身的成员,具有以下特点:

  • 静态类:不能实例化,只包含静态成员

  • 静态成员:所有实例共享,通过类名访问

  • 静态构造函数:在类第一次使用时自动调用

  • 适用场景:工具类、单例模式、常量定义、共享数据

通过合理使用static关键字,可以创建更加高效和组织的代码结构。记住要适度使用,避免过度依赖静态成员导致代码难以测试和维护。


评论