2012-09-13 129 views
11

我想檢查變量是否在運行時以編程方式初始化。爲了讓這個原因不那麼神祕,請看下面不完整的代碼:C# - 檢查變量是否被初始化

string s; 

if (someCondition) s = someValue; 
if (someOtherCondition) s = someOtherValue; 

bool sIsUninitialized = /* assign value correctly */; 

if (!sIsUninitialized) Console.WriteLine(s) else throw new Exception("Please initialize s."); 

並完成相關位。

一個哈克的解決辦法是用默認值來初始化S:

string s = "zanzibar"; 

然後檢查它是否改變了:

bool sIsUninitialized = s == "zanzibar"; 

但是,如果someValuesomeOtherValue發生什麼是「桑給巴爾」以及?然後我有一個錯誤。有更好的方法嗎?

+5

'string.IsNullOrEmpty(s)' – Shmiddty

+7

這實際上不會編譯。變量必須被初始化。只需將它初始化爲null或string.Empty。 – McGarnagle

+0

如果變量被另一個線程初始化會怎麼樣?您是否習慣於設置內存控制器以在寫入訪問時生成異常? – HABO

回答

12

如果編譯器知道某個變量尚未初始化,代碼將不會編譯。

string s; 
if (condition) s = "test"; 
// compiler error here: use of unassigned local variable 's' 
if (s == null) Console.Writeline("uninitialized"); 

在其他情況下,你可以使用關鍵字default如果一個變量可能沒有被初始化。例如,在以下情況下:

class X 
{ 
    private string s; 
    public void Y() 
    { 
     Console.WriteLine(s == default(string)); // this evaluates to true 
    } 
} 

documentation指出缺省(T)會給null對於引用類型,並0值類型。正如在評論中指出的那樣,這與檢查null是非常相似的。


這一切都掩蓋的事實,你應該初始化變量,以null或什麼,當他們第一次聲明。

+4

是不是's ==默認(字符串)'說's == null'的奇特方式? – dasblinkenlight

+1

@dasblinkenlight很好,基本上,但我認爲它使意圖更加明確。 – McGarnagle

+10

@dbaseman,我不同意。它混淆了衆所周知的'null'的用途。 –

2

你可以保持一個獨立的標誌,指示字符串已初始化:

string s = null; 
bool init = false; 
if (conditionOne) { 
    s = someValueOne; 
    init = true; 
} 
if (conditionTwo) { 
    s = someValueTwo; 
    init = true; 
} 
if (!init) { 
    ... 
} 

s分配這會照顧的情況下,包括情況下,當它被分配null,空字符串,或"zanzibar"

另一種解決方法是使靜態字符串表示「未初始化」的值,並使用Object.ReferenceEquals而不是==來檢查它是否已更改。但是,變量方法更明確地表達了您的意圖。

+0

爲什麼介紹這個標誌,而不僅僅是將's'與'null'進行比較? –

+5

@KirkWoll這是一個很好的問題,儘管我試着在答案中回答它:因爲someValueOne或someValueTwo可以合法地爲null。 (更新:顯然,OP不在意:) – dasblinkenlight

+0

夠公平的,我沒有很好地閱讀你的答案。 ;) –

0

我挑選絕不會被用來初始化值,典型值包括String.Emptynull-1和256個字符的隨機字符串發生器。

+2

'string.Empty' ='「」''。不需要使用三倍更詳細的選擇。畢竟,我們不使用諸如'Int32.Zero'之類的東西。 –

+0

我更喜歡String.Empty,因爲它不能與'''混淆。它更易於閱讀。 –

+2

你不應該被'「」混淆。真。它是任何編程語言不可分割的組成部分。 –

3

只是爲它分配默認null,而不是一個字符串值

+0

如果'null'是一個有效值,該字符串將被分配到'if'語句之一中? – Servy

+0

@Servy然後定義一個表示您的非空,未初始化值的常量,例如'const string UninitializedString =「zanzibar」;' –

+1

@PeterGluck那麼這個常量現在變成了「無效」,更糟糕的是,它會使調試變得非常困難,因爲如果某種方法恰好發生了,那麼確定爲什麼它看起來完全不運行會導致各種頭痛。 – Servy

8

在C#2.0中,你有可空操作,使您可以設置空對迄今值類型的初始值,允許這樣的事情:

int? x = null; 

if (x.HasValue) 
{ 
    Console.WriteLine("Value for x: " + num.Value); 
} 

其中收益率: 「x的值:空」。

+2

這不適用於字符串,因爲它已經是引用類型。 – dasblinkenlight

+0

OP的介紹性語句聲明「我想檢查變量是否在運行時初始化」。該類型僅僅是OP所說的是他用於例子的「不完整代碼」的字符串。 –

+2

不要在檢查中使用布爾文字,寫'if(x.HasValue)'。布爾文字只在初始化(或作爲參數傳遞)時纔有意義 - 無處可見。 –

3

這裏有一種方法:

string s; 
if (someCondition) { s = someValue; } 
else if (someOtherCondition) { s = someOtherValue; } 
else { throw new Exception("Please initialize s."); } 

Console.WriteLine(s) 

這可能是最好的檢查,如果該字符串是空的,因爲也許someValue中的是,有時可以返回null的方法。換句話說,也許null是一個合法的值來初始化字符串。

我個人比我更喜歡isInitialized旗。爲什麼要引入一個額外的標誌變量,除非你必須?我不認爲它更具可讀性。

+0

顯然'someValue'不是一種方法,它可能是'SomeValue()',但我的意思是「在實際(非簡化)的情況下」。無論如何它仍然可以是「空」。 –

-1

通常,將默認值分配爲nullString.Empty。對於那些無法使用那些「空」值的情況下,定義一個常數來表示你的應用程序特定的初始化值:

string foo = UnininitializedString; 
if (foo == UninitiaizedString) { 
    // Do something 
} 
:每當你要初始化或測試初始化​​

const string UninitializedString = "zanzibar"; 

然後引用值

請記住,字符串是C#中的不可變常量,因此實際上只有一個UninitializedString實例(這就是比較的原因)。

+1

這是一場災難。在某些情況下,您最終可能會對該「未初始化」值進行合法賦值,導致需要嘗試確定其無法工作的程序員的各種混淆。 – Servy

+0

@Servy並非如此。這就是爲什麼你使用一個命名常量而不是在整個代碼中灑「裸」字符串的原因。常數可以根據需要在路上改變。注意我說你的第一個選擇是使用'null'或'String.Empty'。事實上,'const string UninitializedString = String.Empty;'是我的第一選擇。 –

+1

你永遠不會在整個代碼中首先灑上「裸體」字符串。您使用的解決方案如[this one](http://stackoverflow.com/a/12414058/1159478)從不使用任何值來表示「未初始化的值」。你可以改變它(在編譯時)甚至不會顯着減輕這裏的危險。如果字符串可以基於用戶輸入,那麼在編譯時就不知道用戶可能選擇什麼;不管你選擇什麼,都可能是錯誤的。對於'null'或者一個空字符串有一個有效的賦值其實並不少見,所以使用它將無濟於事。 – Servy