首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 靜態與非靜態成員:記憶體模型、存取規則與實例計數器實戰

     編輯:關於C#

核心定義與記憶體模型

特性靜態成員 (static)非靜態成員 (instance)
所屬類別實例
儲存位置高頻堆 / 靜態欄位槽物件實例記憶體區塊
複製數量每個程式域唯一每個實例一份
初始化時機類別首次存取前 (靜態建構子)每次 new 實例化
生命週期AppDomain 存活期間實例被 GC 回收時結束

宣告與存取語法


class Demo {
    int _instanceField = 1;
    static int _staticField = 2;

    void InstanceMethod() {
        _instanceField = 10;  // OK,隱含 this._instanceField
        _staticField = 20;    // OK,類別名或直接存取
    }

    static void StaticMethod() {
        _staticField = 20;    // OK
        // _instanceField = 10; // CS0120: 需要物件參考
        var d = new Demo();
        d._instanceField = 10; // OK,透過實例參考
    }

    static void Main() {
        Demo._staticField = 5;  // OK,類別名存取靜態
        var d = new Demo();
        d._instanceField = 5;   // OK,實例存取非靜態
        // Demo._instanceField = 5; // CS0120: 類別名不可存取非靜態
    }
}

實戰範例:測試類別展示存取規則


using System;

class Test {
    int x;          // 非靜態
    static int y;   // 靜態

    void F() {
        x = 1;      // OK,等價 this.x = 1
        y = 1;      // OK,等價 Test.y = 1
    }

    static void G() {
        // x = 1;    // CS0120: 無法存取非靜態
        y = 1;      // OK
    }

    static void Main() {
        Test t = new Test();
        t.x = 1;    // OK
        // t.y = 1;  // CS0119: 實例不可存取靜態成員 (建議用類別名)
        // Test.x = 1; // CS0120: 類別名不可存取非靜態
        Test.y = 1; // OK
    }
}

設計決策:何時選用 static?

  • ✅ 單一全域狀態:計數器、快取、設定值、單例實例、統計資料。
  • ✅ 純函式/工具方法:Math.Sin, Enumerable.Where、無副作用邏輯。
  • ✅ 常數/唯讀共享資料:static readonly 組態物件。
  • ❌ 每個實例不同的資料:使用者名稱、視窗座標、連線狀態。
  • ❌ 多執行緒可變狀態:需鎖定/Interlocked/ConcurrentDictionary,否則競爭條件。

記憶體洩漏風險與防範

靜態欄位持有參考型別 → 物件永不被 GC 回收 (除非手動設 null)。


// 危險:靜態清單累積物件
static List _allCustomers = new List();
void Register(Customer c) => _allCustomers.Add(c); // 永不釋放

// 改善:弱參考或定期清理
static List> _refs = new();
void Register(Customer c) => _refs.Add(new WeakReference(c));

效能微觀差異

  • 靜態欄位存取:直接記憶體位址偏移,極快。
  • 非靜態欄位存取:需透過 this 基址 + 偏移,多一層間接。
  • 現代 JIT 高度優化,差異通常可忽略,正確性優先。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved