Home [C# 筆記] static靜態成員 & 實體成員
Post
Cancel

[C# 筆記] static靜態成員 & 實體成員

心得:只有在完全完全確定一個方法不會有結構調整,與系統中其他部分幾乎沒有關聯時,才可以考慮把它寫成靜態方法。 否則,不要用靜態方法!

靜態方法的三大問題:

  • 問題 1:測試困難
  • 問題 2:不靈活
  • 問題 3:靜態傳染
  • 不必要的記憶體浪費
    因為 靜態並非 沒有實體,而是只有一個實體,在程式執行之初就建立,並佔用記憶體位置,而且一直存在
    當程式用上一堆靜態成員的時候,就造成不必要的記憶體浪費。

  • 牽一髮而動全身
    會牽一髮而動全身,靜態成員是唯一的,只要是宣告成 static 且同名的成員,都是共用一區記憶體位置。

static 優缺點

static 的優點

  • 不需要建立物件即可以直接使用。(不用new 就可以使用了)
  • 常駐在記憶體中,在程式碼任何區域都可以直接存取。(在整個專案中「資源共享」) (程式一開始就載入記憶體空間,不會自動進行消毀,直到程式關閉。)

static 的缺點

  • 會長時間佔用記憶體,直到程式關閉。
  • 散佈於各使用區域共享記憶體,可以被隨意修改和使用,難以偵錯和測試。
  • 由於「共享記憶體」,在資料取存時,「多執行緒」下有可能會造成 Race Condition,需再額外處理Lock

【C#】static 使用心得

靜態成員 vs 非靜態成員(實體成員)

  • 靜態的成員 不需要實體(Instance) 就能進行訪問。
  • 非靜態的成員 必須 new 一個 實體(Instance) 才能進行訪問。

  • 靜態方法 屬於 類別(Class)所有。
  • 非靜態方法 屬於 實體(Instance)所有。

  • 靜態成員使用「類別名.靜態成員」去調用。
  • 實體成員使用「物件名.實體成員」去調用。

  • 實體函數中,可以使用靜態成員,也可以使用實體成員。(實體成員+靜態成員)
  • 靜態函數中,只能訪問靜態成員,不允許訪問實體成員。(only 靜態成員)
  • 靜態成員必須使用「類別名」去調用,而實體成員使用「物件名」調用。
  • 靜態函數中,只能訪問靜態成員,不允許訪問實體成員。
  • 實體函數中,既可以使用靜態成員,也可以使用實體成員。
  • 靜態類別中,只允許有靜態成員,不允許出現實體成員。(不能在靜態類別中宣告實體成員)

[C# 筆記] static 靜態與非靜態 by R

實體化

  • 靜態成員屬於類別Class,而不屬於類別的實體Instance。可以透過類別名稱直接存取靜態成員,而不需要建立類別的實體。
  • 非靜態成員屬於類別的實體。要存取非靜態成員,需要先建立類別的實體,然後透過實體來存取成員。
  • 靜態方法 屬於 類別(Class)所有。(使用「類別名.靜態成員」去調用)
  • 非靜態方法 屬於 實體(Instance)所有。(使用「物件名.實體成員」去調用)

記憶體分配

  • 靜態成員在程式啟動時 就分配記憶體,並在程式結束時釋放。它們的生命週期 與應用程式的生命週期相同。
  • 非靜態成員在建立類別的實體時 才分配記憶體,並在實體被銷毀時釋放。它們的生命週期 與實體的生命週期相同。

訪問方式

  • 靜態成員可以透過類別名稱直接訪問,也可以透過實體訪問。但強烈建議使用類別名稱來存取靜態成員,以明確它們的靜態性。
  • 非靜態成員只能透過實體存取。
  • 實體函數中,可以使用靜態成員,也可以使用實體成員。(實體成員+靜態成員)
  • 靜態函數中,只能訪問靜態成員,不允許訪問實體成員。(only 靜態成員)

this 關鍵字

  • 靜態成員中 不能使用 this 關鍵字,因為它們不屬於實體。
  • 非靜態成員中 可以使用 this 關鍵字來引用目前實體。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Test
{
    public static int staticNumber = 10; //靜態成員
    public int InstanceNumber = 20; //非靜態成員

    //靜態方法
    public static void StaticMethod()
    { 
        // 靜態方法: 不能使用 this 關键字
        Console.WriteLine("Static Method:");
    }

    //非靜態方法
    public void InstanceMethod()
    {
        // 非靜態方法: 可以使用 this 關键字
        Console.WriteLine($"Instance Method: {this.InstanceNumber}");
    }
}

使用場景

  • 靜態成員通常用於表示 與整個類別相關的資料或功能,例如共用的計數器、工廠方法等。
  • 非靜態成員通常用來表示 實體特有的資料或功能,每個實體都有獨立的值。

[C# 筆記] 靜態成員和非靜態成員的區別 by R

什麼時候用靜態類別?

使用時機

  • 如果你想要你的類別(Class)當做一個「工具」去使用(經常使用),就可以考慮使用靜態類別。
  • 靜態類別在整個專案中「資源共享」。(共享記憶體)
  • 靜態類別在專案中儘量不要太多,因為它會消耗你的資源。(它一開始載入時就存在,所以就會佔據記憶體空間)
  • 「靜態類別」是佔記憶體。(程式一開始就載入記憶體)
  • Class類別」是不佔記憶體,「實體」是佔記憶體。(new實體化後才會記憶體)

物件實體方法與靜態方法的疑問

在設計類別時,如果會有需要讓用戶端(呼叫它的程式)直接使用而不必產生物件實體的話,可以把它設計為 static. static 也可以用來提供全域性(Global)的成員,包含變數,常數或函式 . 但它的缺點是在程式一開始就載進記憶體,直到程式終止,過多的靜態成員會佔住很多的記憶體 .

如果你要讓類別必須在做一些事情(初始化,載入資料)才能給用戶端取用時,就不必設計為 static. 這樣它就只會在載入時才會佔用記憶體,並且會在類別被終止(設定物件變數為 null 或是呼叫自己的摧毀物件方法,例如 Dispose())時會釋放出記憶體,缺點就是要呼叫前都要建立物件實體 .

MSDN - 靜態類別和靜態類別成員 (C# 程式設計手冊) 一秒看破 static
【C#】static 使用心得 为什么应该少用静态(static)方法:静态方法的三大问题
[C# 筆記] static 靜態與非靜態 by R
[C# 筆記] class property method field review by R
[C# 筆記] 靜態和非靜態的區別 by R
[C# 筆記] 靜態成員和非靜態成員的區別 by R

This post is licensed under CC BY 4.0 by the author.

[C# 筆記] Using 作用

[C# 筆記] 介面與實作