2011-09-08 77 views
0

我讀由Microsoft AppHub樣品,這是功能之一的開頭:爲什麼C#不允許變量在方法中聲明爲靜態?

if (string.IsNullOrEmpty(textureFilename)) 
{ 
    string message = "textureFilename wasn't set properly, so the " + 
     "particle system doesn't know what texture to load. Make " + 
     "sure your particle system's InitializeConstants function " + 
     "properly sets textureFilename."; 
    throw new InvalidOperationException(message); 
} 

ReSharper的說,使這個值恆定的,而不是每次都重新聲明它。但是,此字符串值僅用於此函數,因此使其成爲成員變量不應該是必需的。理想情況下,變量的範圍應限於此功能。對?

此外,我同意誰要說「將字符串放在資源文件中」。在這種情況下,這很可能是最佳解決方案。它不僅解決了本地化問題,而且還保存了每次函數調用時重新初始化的變量,並且不再混淆源文件。但是,這只是一個例子。

我知道很多人可能會說「過早優化是萬惡的根源」,但請注意這僅僅是一個例子。如果這個準常量變量很複雜並且重新初始化它,每次調用都會導致明顯的減速?

Visual Basic .NET允許程序員將函數中的變量聲明爲靜態。例如,在這個代碼TestFunction將只能被稱爲第一次我按一下按鈕:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
    Static example As Integer = TestFunction() 

    MessageBox.Show(example) 
End Sub 

Private Function TestFunction() As Integer 
    Console.WriteLine("Method Accessed") 

    Return 5 
End Function 

據我所知,C#不允許這樣做。有什麼特別的原因嗎?在這種情況下,它似乎是完美的。它將變量範圍限制爲函數,並且僅在第一次初始化它。即使對象創建成本高昂,它也只會執行一次。那麼爲什麼這不可用?或者是?

感謝您的閱讀!

+0

我不知道爲什麼它不可用。 (可能是因爲VB.NET是一種稍微好一點的語言:])使它成爲一個成員變量並不壞 - 雖然在範圍方面存在一些問題,但單一類文件應該由同一個人編寫,它應該是顯而易見的變量。 – Ryan

+0

VB中的靜態「本地」只是一個編譯器技巧。生成的IL與您使用類級別的靜態字段(除了編譯器生成的名稱之外)沒有區別。 – LukeH

回答

4

ReSharper的說,使這個值恆定的,而不是重新聲明每次 它。但是,此字符串值僅用於此 函數,因此使其成爲變量不應該是必需的。 理想情況下,變量的作用域應該限制在這個函數中。 對不對?

是的,但ReSharper的會使局部變量常量,而不是創建一個成員字段

if (string.IsNullOrEmpty(textureFilename)) 
{ 
    const string message = "textureFilename wasn't set properly, so the " + 
     "particle system doesn't know what texture to load. Make " + 
     "sure your particle system's InitializeConstants function " + 
     "properly sets textureFilename."; 
    throw new InvalidOperationException(message); 
} 
+0

嘿,雞蛋在我臉上。我不知道你可以在方法中使用常量變量。在一個方法中的靜態變量沒有工作後,我甚至都不想嘗試靜態方法。另外,我想我假設如果微軟可能會在他們的代碼中完成它。哦,謝謝! –

+0

@Kyle:當然你不能有「常量變量」,因爲「常量」和「變量」是*相反的*。 (你可以有局部常量,但它們不是「常量變量」。)在C#中沒有辦法在本地範圍內使用靜態字段;如果你想要一個靜態字段,那麼創建一個私有的類作用域靜態字段。 –

1

ReSharper建議您有什麼理由不想讓它成爲本地const

if (string.IsNullOrEmpty(textureFilename)) 
{ 
    const string message = "..."; 
    throw new InvalidOperationException(message); 
} 
+0

O_O不知道你能做到這一點。老實說,我甚至不打算重新調整它,因爲我認爲它只是將其作爲班級中不變的成員變量。 –

1

有一個blog post in the C# FAQ about this exact question

實際上,有兩個原因。首先,在幾乎所有情況下,您都可以通過const或通過成員級別的靜態變量完成相同的任務。其次,其他語言(如C和C++)中的局部靜態變量在多線程場景中經常會導致問題。

此外,我很高興這被遺漏了。作爲數據,說明它在C#中的使用方式,只存在於一個類型或一個實例。這將成爲第三種存儲狀態的方式,並增加混淆。至於爲什麼VB.Net包括這個 - 這是爲了向後兼容VB。話雖如此,編譯器實際上把它變成了這個類型的一個靜態成員,所以它和C#的支持程度相同。

相關問題