2008-10-29 75 views
5

我在前一段時間發現(我想再次確認),如果您聲明瞭一個類級別的變量,那麼在調用類構造函數或加載之前,您不應該調用它的構造函數。原因是表現 - 但還有其他原因要做還是不做?這個規則是否有例外?聲明變量 - 最佳實踐

即:這是我做的依據是什麼,我認爲最好的做法是什麼:

public class SomeClass 
{ 
    private PersonObject _person; 

    public SomeClass() 
    { 
     _person = new PersonObject("Smitface"); 
    } 
} 

反對:

public class SomeClass 
{ 
    private PersonObject _person = new PersonObject("Smitface"); 

    public SomeClass() 
    { 

    } 
} 

回答

12

如果你在構造函數之外設置你的變量,那麼沒有可用的錯誤處理(handeling)。雖然在你的例子中它沒有區別,但有很多情況下你可能想要進行某種錯誤處理。在這種情況下,使用你的第一個選項是正確的。

Nescio談到了如果有一些構造函數失敗,這會對你的應用產生什麼影響。

因此,我總是使用選項#1。

0

我更喜歡後者,但只有監守我覺得它很整潔。

真的是個人喜好,他們都做同樣的事情。

6

老實說,如果你看一下IL,第二種情況發生的所有事情就是編譯器將初始化移動到構造函數中。

個人而言,我喜歡在構造函數中看到所有的初始化。如果我正在做一個一次性原型項目,我不介意在同一個地方進行初始化和聲明,但對於我的「我想保留這個」項目,我在構造函數中完成了所有工作。

-3

我寧願儘快初始化變量,因爲它避免(一些)空錯誤。

編輯:顯然在這個簡化的例子中沒有區別,但是在一般情況下,我認爲如果可能的話,在聲明類變量時初始化它是個好習慣。這使得在它初始化之前不可能引用該變量,這消除了在初始化構造函數中的字段時可能會出現的一些錯誤。

隨着您獲得更多類變量,並且構造函數中的初始化序列變得更加複雜,在一個初始化依賴於另一個尚未發生的初始化的情況下,可以更容易地引入錯誤。

+0

您的評論並不真正適用在這裏。無論使用哪種方法,變量都將同時進行初始化。 – Herms 2008-10-29 18:40:22

+0

評論者的編輯評論有一個好處 - 如果我有一個字段與初始化,我知道它將被初始化。如果我在一個包含20個構造函數的類中有一個字段,那麼很難確保變量在被使用之前被初始化。 Eric Lippert的帖子使這更加真實。 – 2008-10-29 23:16:39

1

它取決於如何使用變量的上下文。自然地,常量和靜態或只讀應該在聲明時初始化,否則它們通常應該在構造函數中初始化。通過這種方式,您可以將設計模式換成相當容易安裝的對象,而無需擔心變量何時被初始化。

+0

你永遠無法單獨設定構造函數的假設,因爲語言允許你以另一種方式進行。如果你導入一些你去年寫過的代碼呢?希望你不要改變模式。 (在這種情況下,似乎生成的IL是等價的,但也可能有其他的) – 2008-10-29 18:42:13

0

第一個聲明實際上更乾淨。第二個隱藏了構造函數在靜態構造函數中初始化類的事實。如果由於任何原因構造函數失敗,則整個類型對於其餘的應用程序是不可用的。

+0

靜態構造函數?在這個例子中,我沒有看到任何靜態的東西。 – 2008-10-29 23:05:11

0

我喜歡在構造函數中進行初始化,因爲這種方式都發生在一個地方,也因爲如果您決定稍後創建一個重載的構造函數,它會更容易。

此外,它有助於提醒我要在解構器中清理的事情。

0

後者可以採取延遲實例化的優勢,即直到它被引用

0

我認爲這類型的問題不僅是風格,所以誰在乎你做了什麼方式,它不會初始化變量。該語言允許兩種語言,所以其他人都會這樣做。不要做出錯誤的假設。

4

其實,不管別人怎麼說,它可以重要的你是否初始化內部或構造函數外,因爲有對象的構造過程中不同的行爲,如果對象是層次結構(即順序哪些事情運行是不同的)。

請參閱Eric Lippert的this postthis post,它更詳細地解釋了兩者之間的語義差異。

所以答案是,在大多數情況下,它沒有任何區別,它在性能方面肯定沒有任何區別,但是在少數情況下,它可以帶來不同,你應該知道爲什麼,並據此作出決定。

1

您通常應該更喜歡第二個變體。對代碼的更改更強大。假設你添加一個構造函數。現在你必須記得初始化你的變量,除非你使用第二個變體。

當然,只有在沒有令人信服的理由才能使用構造函數初始化時(如discorax所述),纔會計數。

2

有一種稱爲依賴注入或控制反轉(IOC)的通用模式,它提供了這樣兩種機制,用於將依賴對象(如DAL類)「注入」到依賴關係鏈中的類(遠離數據庫)

在這個模式中,使用構造函數,你會

公共類SomeClass的
{每
私人PersonObject;

public SomeClass(PersonObject person) 

{  
    per = person; 
} 

}

私人PersonObject喬=新PersonObject( 「Smitface」);

SomeClass MyObj = new SomeClass(Joe);

現在你能夠例如,通過在生產呼叫 或在單元測試方法測試DAL類真正的DAL類...