2016-10-28 49 views
1

我今天和一位同事討論瞭如何最好地返回兩個值。 我們有三種不同的觀點。重要的是,我們不能使用額外的類或結構(因此沒有元組),這是這個問題中最好的答案:Clean Code - Are output parameters bad?返回值與參考值相比較輸出值

public enum Offset 
{ 
    None = 0, 
    Training = 10, 
    Cancel = 20 
} 

static void Main(string[] args) 
{ 
    //Option 1 
    int outValue = 0; 
    Offset outOffset; 
    HandleOffset(35, out outValue, out outOffset); 

    //Option 2 
    int refValue = 0; 
    outOffset = SubtractOffset(ref refValue); 

    //Option 3 
    outOffset = GetOffsetById(35); 
    int id = GetIdWithoutOffset(35); 
} 

//Option 1 
public static void HandleOffset(int inValue, out int outValue, out Offset outOffset) 
{ 
    outValue = inValue; 
    outOffset = Offset.None; 
    if ((inValue-(int)Offset.Cancel)>15) 
    { 
     outValue -= (int)Offset.Cancel; 
     outOffset |= Offset.Cancel; 
    } 
    if ((inValue - (int)Offset.Training) > 15) 
    { 
     outValue -= (int)Offset.Training; 
     outOffset |= Offset.Training; 
    } 
} 

//Option 2 
public static Offset SubtractOffset(ref int id) 
{ 
    Offset offset = Offset.None; 
    if ((id - (int)Offset.Cancel) > 15) 
    { 
     id -= (int)Offset.Cancel; 
     offset |= Offset.Cancel; 
    } 
    if ((id - (int)Offset.Training) > 15) 
    { 
     id -= (int)Offset.Training; 
     offset |= Offset.Training; 
    } 
    return offset; 
} 

//Option 3 
public static Offset GetOffsetById(int id) 
{ 
    Offset offset = Offset.None; 
    if ((id - (int)Offset.Cancel) > 15) 
    { 
     offset |= Offset.Cancel; 
    } 
    if ((id - (int)Offset.Training) > 15) 
    { 
     offset |= Offset.Training; 
    } 
    return offset; 
} 

//Option 3 
public static int GetIdWithoutOffset(int id) 
{ 
    if ((id - (int)Offset.Cancel) > 15) 
    { 
     id -= (int)Offset.Cancel; 
    } 
    if ((id - (int)Offset.Training) > 15) 
    { 
     id -= (int)Offset.Training; 
    } 
    return id; 
} 

由於返回值+ ref值,選項2看起來很難看。

選項1,似乎也是醜陋的,因爲這兩個輸出參數,但是實際上它看起來比第二個選項清潔。

選項3對我來說看起來最清潔。

哪個這些解決方案被認爲是最清潔溶液(如清潔通過鮑伯馬丁乾淨的代碼),或者是有其他的選擇來解決這個問題,我們可能沒有想到的?

+0

性能差異是什麼?如果對性能關鍵代碼有一個主要的加速,我可以理解ref/out的需求,但是我認爲如果您想要找到像「bob martin的乾淨代碼」那樣乾淨的選項,那麼選項3是最接近的。一般來說,我公司的人員傾向於避免參考/輸出參數,因爲這是您的方法試圖做得太多的指標。 –

+0

選項4:2個函數,每個函數只是'返回' – zerkms

+0

@zerkms你能解釋一下你的解決方案嗎?選項3有什麼區別? – Bongo

回答

1

一般來說,最乾淨的解決方案是不需要任何outref-參數(最好是一個結構/類,元組也可以工作)。由於不允許使用類/結構體或元組,這將是首選方式,所以我仍然使用第一個選項作爲最簡單的方法。

在我看來,第二種選擇是完全廢話,因爲out -keyword應該完全按照你想要的來做,所以使用ref根本就沒有必要。

第三個選項是好的,雖然很混亂,沒那麼容易。既然你不能使用元組並且想要保持一個清晰的代碼,那就避免它。

TL; DR:使用第一個選項。

1

我只是要拋出這個在那裏,但我絕不會做這種生產(至少一個公共API)。

另一種選擇是使用一個dynamic返回類型。沒有參數。沒有參考參數。只是模糊的返回值:

public class Program 
{ 
    public static void Main() 
    { 
     dynamic offset = HandleOffset(); 

     Console.WriteLine(offset); 
    } 

    public static dynamic HandleOffset() 
    { 
     return new 
     { 
      Value = 64, 
      Offset = Offset.Cancel 
     }; 
    } 
} 

public enum Offset 
{ 
    None = 0, 
    Training = 10, 
    Cancel = 20 
} 
+0

哇,這很有趣。我同意如果我有不同的選擇,我不想在生產中使用它,但這非常有趣。 +1 – Bongo