2013-07-31 77 views
3

爲什麼C#允許在非靜態構造器中初始化靜態類變量?靜態變量應該只允許在靜態構造函數上初始化。有任何想法嗎?爲什麼C#允許在非靜態構造器中初始化靜態類變量?

public class customer 
{ 
    public string Name; 

    public customer() 
    { 
     Name = "C1"; 
     Console.WriteLine("creating customer " + Name); 
    } 

} 

class Program 
{ 
    public static customer cust; 

    public Program() 
    { 
     cust = new customer(); //Why is this allowed i.e. initialize a static variable in non-static constructor? 
    } 

    static void Main(string[] args) 
    { 
     Program program = new Program(); 
     program = new Program(); 

     Console.Read(); 
    } 
} 
+5

爲什麼它不應該允許這個?如果你想在第一次實例化類時初始化一個靜態變量呢?或者,也許每次增加一個對象時都會增加一個計數。 –

+2

你可以從* any *方法更新它,沒有什麼特別的構造函數。你忘記宣佈它*只讀*? –

回答

10

不要將它看作初始化,將它看作設置。

如果您只想通過靜態構造函數或聲明初始化它,請添加readonly關鍵字。

E.g.

public readonly static customer cust; 

//Allowed 
static Program() 
{ 
    cust = new customer(); 
} 

//Not Allowed 
public Program() 
{ 
    cust = new customer(); 
} 
+0

因此靜態關鍵字本身不足以強制單個初始化?這種行爲與C++不同。 – naveed

+6

@naveed c#不是C++。 –

0

這只是意味着靜態變量在每次新對象初始化時都會被重置。有點奇怪,但編譯器允許它。

+0

是的,真的。沒有意義。如果我同時聲明和初始化靜態變量,那麼它只被初始化一次。 – naveed

+0

@naveed你錯過了這一點。你是一個做傻事的人,不是編譯器。靜態構造函數處理初始化靜態成員,但是,靜態僅僅意味着「無需實例即可訪問」,而不是「僅可賦值一次」。如果您希望該字段只能賦值一次,那麼在構造函數中,可以使用'readonly'關鍵字。不要認爲,由於關鍵字與其他語言具有相同的名稱,因此它必須相同。 C++中的'static'在概念上是相似的,但仍然不同於C#中的'static'。另外,你不需要在C++中聲明'const static'嗎? – Luaan

2

您可以從任何非靜態函數中訪問和修改一個靜態變量,每次調用它時都會覆蓋該值。但事實並非如此 - 靜態函數不能訪問非靜態變量。

4

簡短的回答是沒有理由不讓這個。靜態變量可以在類內部的任何地方(如果它們是公共的,那麼外部的)也可以到達,構造函數也不例外。這包括更改它們的值或將它們初始化爲新值。

事實上,有幾種模式可以利用這種行爲。例如,第一次實例化一個類時初始化一個靜態對象(可能是爲了緩存初始化開銷很大但未來不會改變的屬性)。另一個用途可能是增加一個計數器來跟蹤這些對象中有多少活着。這就是說,你需要在初始化之前瞭解類中的靜態對象,並在覆蓋它們的值之前檢查它們是否爲空。

相關問題