2010-03-15 48 views
5

假設具有以下簽名當TryXxxx方法返回false時,out參數的標準行爲是什麼?

bool TryXxxx(object something, out int toReturn) 

它有什麼toReturn可以接受的,如果TryXxxx返回false的方法?

因爲它的傳染toReturn永遠不應該使用,如果TryXxxx失敗有什麼關係?

如果toReturn是一個nulable類型,那麼返回null是有意義的。但int是不可空的,我不想強​​迫它。

如果toReturn總是一個確定的值,如果TryXxxx失敗,我們冒險有2個值可以被視爲指示相同的事情的位置。如果將「默認」值作爲有效響應返回(當TryXxxx返回true時),我可以看到這會導致潛在的混淆。

從實施點看,如果看起來像有toReturn是[ny]值最簡單,但是還有什麼更重要的考慮?

回答

6

我會明確文檔它作爲使用的默認值的類型(不管其類型是;在這種情況下,所以0但default(T)在更一般的情況)。有多種情況下,如果值不存在,默認值就是您想要的值 - 在這種情況下,您可以忽略該方法的返回值。

請注意,這是像int.TryParseDictionary.TryGetValue這樣的方法。

+0

此外,如果你關心的結果足夠,你不想使用默認值,除非這是顯式的值是XYZ(解析等)。),那麼你真的應該檢查方法的返回值。 – 2010-03-15 11:17:18

+0

如果嘗試返回false,沒有考慮消費者有理由使用返回的值。 – 2010-03-15 12:06:10

4

這可能是default(int)

bool TryXxxx(object something, out int toReturn) 
{ 
    toReturn = default(int); 
    return false; 
} 
2

我會說default,但實際上它不應該的問題。使用TryX的約定是,調用者應該檢查返回值,並且只在方法返回true時使用out參數。

2

基本上它是東西。我會將其記錄爲「未定義」。明智的值是:

  • 默認()
  • MINVALUE,MaxCValue,NEWVALUE(如新INT()),空
  • NAN值(Double.NaN)

但在一般情況下,我真的會說「沒有定義」,不給人們可能會依賴的東西。

+0

理論上,您可以將方法記錄爲給出「未定義」行爲,但實際上您需要提供具體的實現。是的,你可以返回一個隨機值,也許會引發潛伏的bug,但實際的解決方案通常是返回一個固定的默認值,因此「default(T)」可能是最好的值。還要注意,在這種情況下,您仍然可以將該方法記錄爲給出未定義的行爲,如果需要,您可以選擇稍後更改該值。但是,我可能會自己返回一個固定的默認值。 – 2010-03-15 11:18:46

0

1)實際上,我認爲它應該沒有關係,因爲您應該總是在處理值之前檢查這些方法的布爾結果。這就是TryXXX方法的用途。

2)但是,在這種情況下,我總是參考.NET框架中的實現來保證一致性。並快速查看反射表明的Int32類型返回0,如果解析失敗:

internal static unsafe bool TryParseInt32(string s, NumberStyles style, NumberFormatInfo info, out int result) 
{ 
    byte* stackBuffer = stackalloc byte[1 * 0x72]; 
    NumberBuffer number = new NumberBuffer(stackBuffer); 
    result = 0; // <== see here! 
    if (!TryStringToNumber(s, style, ref number, info, false)) 
    { 
     return false; 
    } 
    if ((style & NumberStyles.AllowHexSpecifier) != NumberStyles.None) 
    { 
     if (!HexNumberToInt32(ref number, ref result)) 
     { 
      return false; 
     } 
    } 
    else if (!NumberToInt32(ref number, ref result)) 
    { 
     return false; 
    } 
    return true; 
} 

然而,不知道實施細則,但仍可能發生,當值已經被分配發生解析問題(部分)。在這種情況下,該值可能不再是0.因此,您應該始終堅持「解決方案」1)! :-)

gehho。

0

在.net之前,一個正常的模式是TryXX方法可以簡單地保持傳引用參數參數不被修改。這是一個非常有用的模式,因爲這意味着代碼要使用默認值可以這樣做:

MyNum = 5; 
TryParsing(myString, &myNum); 

而代碼,不希望使用默認值,可以使用:

if (TryParsing(myString, &myNum)) 
{ .. code that uses myNum .. } 
else 
{ .. code that doesn't use myNum .. } 

在前面的用法中,調用代碼必須確保myNum在調用之前被初始化,但不必擔心TryParsing的返回值。在後一種用法中,調用代碼將不得不擔心返回值,但不必在調用之前初始化myNumTryParsing例程本身不必擔心使用的是哪一種。

但是,C#並不能很好地允許這種模式,除非TryParsing用另一種語言編寫。必須寫入TryParsing,以便前面的值myNum將被無條件覆蓋而未經檢查,調用者必須無條件地初始化它,或者必須爲這兩種情況提供不同的方法。如果TryParsing方法是用其他語言編寫的,它理論上可以像舊式方法一樣工作(在成功時寫入參數,如果不是,則保持原樣),同時仍將其稱爲out參數。然而,我不會推薦這個,因爲古怪的行爲不會侷限於out參數。

考慮,例如,該樣式的方法使用fooStruct類型的參數,並fooStruct有一個看起來像一個構造函數:

fooStruct(string st) 
{ 
    fooStruct.TryParse(st, out this); 
} 

,編譯器將是這樣的構造非常高興,因爲它「絕對」寫道this。在另一方面,如果一些其他的代碼呢:

while(someCondition) 
{ 
    var s = new fooStruct(someString); 
    ... 
} 

人們可能會想到的是s要麼持有的初始化結構(如someString是有效的),或者是空白的(如果不是)。該代碼沒有任何暗示s可以在循環的重複之間保持其值。儘管如此,這正是可能發生的情況。

相關問題