2009-07-17 49 views
10

如果我運行此C#代碼爲什麼Int32.TryParse在無法轉換時重置out參數?

int realInt = 3; 
string foo = "bar"; 
Int32.TryParse(foo, out realInt); 

Console.WriteLine(realInt); 
Console.Read(); 

我得到0。而且我想知道爲什麼!因爲我找不到任何原因。這迫使我爲每個解析創建臨時變量。所以,請!偉大的宇宙編碼者,賜教!

+0

我格式化代碼爲您服務。下一次,如果您不確定如何在MarkDown編輯器中設置格式,請使用文本區域上方的小工具欄。有一個代碼格式化選項。 – OregonGhost 2009-07-17 08:31:40

+0

感謝您的幫助=) – 2009-07-17 08:49:00

回答

33

它是「out」,而不是「ref」。在該方法內部,具有來分配它(不先讀取它)以滿足「out」的含義。

實際上,「out」是一個語言問題(不是框架之一) - 所以託管的C++實現可能會忽略這個......但是它更符合它的要求。

實際上,如果該方法返回false,則不應該查看該值;將其視爲垃圾直到下一次分配。它聲明返回0,但這是很少有用的。


此外 - 如果它沒有這樣做(即如果它保存了值);這個打印:

int i; 
int.TryParse("gibber", out i); 
Console.WriteLine(i); 

這是完全有效的C#...所以它打印什麼?

+2

*爲什麼*它是這樣的解釋,以便您可以斷言在TryParse調用後的任何代碼中變量* always *都已設置,即使變量在代碼的前面沒有初始化(所以編譯器在`TryParse`調用之後使用該變量時不會引發錯誤;嘗試對使用`ref`關鍵字的函數執行相同操作。) – Blixt 2009-07-17 08:16:42

6

The Int32.TryParse Method (String, Int32) doc說:

一個數字的字符串表示形式轉換爲它的32位帶符號整數等效。返回值指示轉換是否成功。

結果

類型:System.Int32

此方法返回時,包含32位帶符號整數的值等效於包含在S中的號碼,如果轉換成功,或者零,如果轉換失敗。如果s參數爲空引用(在Visual Basic中爲Nothing),格式不正確,或者表示小於MinValue或大於MaxValue的數字,則轉換將失敗。此參數未經初始化傳遞。

+0

@Luke - look以粗體顯示... – 2009-07-17 08:08:02

0

因爲(至少在C#中)帶有一個或多個輸出參數的方法必須保證它們回寫給它們。這樣,在將方法作爲參數傳遞給方法之前,您不需要在方法中初始化本地字段。

0

我的猜測是,這是在C#規範的一部分:

10.5.1.3輸出參數 ... 在方法內部,就像一個局部變量,輸出參數最初考慮>未分配必須在使用其值之前明確分配。

在方法返回之前,方法的每個輸出參數都必須明確賦值。

如果是這種情況,您不應該依賴結果值。

0

由於TryParse的第二個參數是out參數,因此TryParse方法被強制初始化參數。如果參數是ref而不是out,您將得到您想要的行爲。但是,由於TryParse方法只需要輸出一個數字,並且不會獲得任何數字,因此輸入out是參數的正確選擇。

2

因爲這是'out'合同的工作方式。每當你將一個out參數傳遞給一個函數時,它的函數的責任就是初始化它。

1

Int32.TryParse MSDN文檔指出,如果轉換失敗,結果將始終返回0

你通常應該要麼使用一個臨時結果變量即

int value; 
bool succeeded = Int32.TryParse("astring", out value); 
if (succeeded) 
{ 
    // use value in some way 
} 

,或者你只是包裹在if語句中完整的方法

int value; 
if (Int32.TryParse("astring", out value)) 
{ 
    // use value in some way 
} 

我個人認爲後者是更好的選擇。

4

由於該參數是一個輸出參數,所以當您聲明它時,您不必初始化realInt,因爲編譯器可以看到您將它傳遞給一個保證將其設置爲某事的方法(因爲的「出」)。

現在,因爲它是一個輸出參數,所以需要TryParse將其設置爲某個值。它將它設置爲0,因爲這是C#中大多數情況下int的默認值。

你可以寫爲:

int realInt; 
string foo="bar"; 
if(int.TryParse(foo,out realInt)==false) 
{ 
    realInt=3; 
} 
1
public static class IntHelper 
{ 
    public static bool TryParse(string s, ref int outValue) 
    { 
     int newValue; 
     bool ret = int.TryParse(s, out newValue); 
     if (ret) outValue = newValue; 
     return ret; 
    } 
} 
相關問題