2010-07-26 78 views
9

我怎樣才能結合returnswitch case陳述?聯合收益和開關

我想是這樣

return switch(a) 
     { 
      case 1:"lalala" 
      case 2:"blalbla" 
      case 3:"lolollo" 
      default:"default" 
     }; 

我知道這個解決方案

switch(a) 
{ 
    case 1: return "lalala"; 
    case 2: return "blalbla"; 
    case 3: return "lolollo"; 
    default: return "default"; 
} 

但我想只用return操作。

+0

AFAIK,切換不會返回值,因此您的使用是不可能的。 爲什麼你想這樣做? – SWeko 2010-07-26 11:05:38

回答

19

switchreturn不能結合這種方式,因爲switch語句,而不是一個表達(即,它不返回一個值)。
如果你真的想只使用一個單一的return,你可以做一個解釋的開關變量映射到返回值:

var map = new Dictionary<int, string>() 
{ 
    {1, "lala"}, 
    {2, "lolo"}, 
    {3, "haha"}, 
}; 
string output; 
return map.TryGetValue(a, out output) ? output : "default"; 
0
public String doStaff(int a) { 

    switch(a) 
     { 
      case 1: return "lalala" 
      case 2: return "blalbla" 
      case 3: return "lolollo" 
      default: return "default" 
     }; 
} 
3
switch(a) 
{ 
    case 1: return "lalala"; 
    case 2: return "blalbla"; 
    case 3: return "lolollo"; 
    default: return "default"; 
} 
12

我通常做這種方式:

var result = null; 

switch(a) 
{ 
    case 1: 
     result = "lalala"; 
     break; 
    case 2: 
     result = "blalbla"; 
     break; 
    case 3: 
     result = "lolollo"; 
     break; 
    default: 
     result = "default"; 
     break; 
}; 

return result; 
+0

爲什麼這優於提前退出,它具有較少的代碼和較少的變量? – 2010-07-26 15:57:57

+7

這不是優越的,但問題是隻有一個返回語句,這就是隻有一個。 – Oliver 2010-07-27 06:25:25

15

我相信這個解決方案是最直接的解決方案,你應該使用它:

switch(a) { 
    case 1: return "lalala"; 
    case 2: return "blabla"; 
    case 3: return "lololo"; 
    default: return "default"; 
} 

但是,既然你問了一個return,你可以使用這個小流利類:

public class Switch<TElement, TResult> { 
    TElement _element; 
    TElement _currentCase; 
    IDictionary<TElement, TResult> _map = new Dictionary<TElement, TResult>(); 

    public Switch(TElement element) { _element = element; } 
    public Switch<TElement, TResult> Case(TElement element) { 
    _currentCase = element; 
    return this; 
    } 
    public Switch<TElement, TResult> Then(TResult result) { 
    _map.Add(_currentCase, result); 
    return this; 
    } 
    public TResult Default(TResult defaultResult) { 
    TResult result; 
    if (_map.TryGetValue(_element, out result)) { 
     return result; 
    } 
    return defaultResult; 
    } 
} 

像這樣創建代碼:

return new Switch<int, string>(a) 
    .Case(1).Then("lalala") 
    .Case(2).Then("blabla") 
    .Case(3).Then("lololo") 
    .Default("default"); 

不幸的是,類型參數不能由編譯器推斷,而且感覺有點笨拙。 Default將觸發對「開關」的評估,並且必須是鏈中最後的方法調用。請注意,您始終需要一個默認值,因爲您已將switch轉換爲表達式。

UPDATE:你能解決這個類型推斷問題和驅動用戶做正確的事與此代碼:

public static class Switch { 

    public static SwitchBuilder<TElement>.CaseBuilder On<TElement>(TElement element) { 
    return new SwitchBuilder<TElement>(element).Start(); 
    } 

    public class SwitchBuilder<TElement> { 
    TElement _element; 
    TElement _firstCase; 
    internal SwitchBuilder(TElement element) { _element = element; } 
    internal CaseBuilder Start() { 
     return new CaseBuilder() { Switch = this }; 
    } 
    private ThenBuilder Case(TElement element) { 
     _firstCase = element; 
     return new ThenBuilder() { Switch = this }; 
    } 
    private SwitchBuilder<TElement, TResult>.CaseBuilder Then<TResult>(TResult result) { 
     return new SwitchBuilder<TElement, TResult>(
     _element, 
     _firstCase, 
     result).Start(); 
    } 
    public class CaseBuilder { 
     internal SwitchBuilder<TElement> Switch { get; set; } 
     public ThenBuilder Case(TElement element) { 
     return Switch.Case(element); 
     } 
    } 
    public class ThenBuilder { 
     internal SwitchBuilder<TElement> Switch { get; set; } 
     public SwitchBuilder<TElement, TResult>.CaseBuilder Then<TResult>(TResult result) { 
     return Switch.Then(result); 
     } 
    } 
    } 

    public class SwitchBuilder<TElement, TResult> { 
    TElement _element; 
    TElement _currentCase; 
    IDictionary<TElement, TResult> _map = new Dictionary<TElement, TResult>(); 
    internal SwitchBuilder(TElement element, TElement firstCase, TResult firstResult) { 
     _element = element; 
     _map.Add(firstCase, firstResult); 
    } 
    internal CaseBuilder Start() { 
     return new CaseBuilder() { Switch = this }; 
    } 
    private ThenBuilder Case(TElement element) { 
     _currentCase = element; 
     return new ThenBuilder() { Switch = this }; 
    } 
    private CaseBuilder Then(TResult result) { 
     _map.Add(_currentCase, result); 
     return new CaseBuilder() { Switch = this }; 
    } 
    private TResult Default(TResult defaultResult) { 
     TResult result; 
     if (_map.TryGetValue(_element, out result)) { 
     return result; 
     } 
     return defaultResult; 
    } 
    public class CaseBuilder { 
     internal SwitchBuilder<TElement, TResult> Switch { get; set; } 
     public ThenBuilder Case(TElement element) { 
     return Switch.Case(element); 
     } 
     public TResult Default(TResult defaultResult) { 
     return Switch.Default(defaultResult); 
     } 
    } 
    public class ThenBuilder { 
     internal SwitchBuilder<TElement, TResult> Switch { get; set; } 
     public CaseBuilder Then(TResult result) { 
     return Switch.Then(result); 
     } 
    } 
    } 

} 

結果是這樣的漂亮,類型安全,流暢的界面;其中,在每一步你只有方法正確的選擇調用(如CaseThen):

return Switch.On(a) 
    .Case(1).Then("lalala") 
    .Case(2).Then("blabla") 
    .Case(3).Then("lololo") 
    .Default("default"); 
+2

這很好,Jordao,但是將方法作爲Thens的參數(他們可能是匿名的)會更有意義。就像一個正常的案例陳述。 case語句中可以有多行代碼。所以,你可以說int x = b + c * d;返回「答案是」+ a.ToString();例如。無論如何,它必須是一個返回(在On子句中)相同類型的對象的方法。合理? – vbullinger 2012-06-21 22:17:05

+1

@vbullinger:是的,它非常有意義。事實上,這正是我之前開始做的事情,但並沒有真正完成。 – 2012-06-21 23:13:49

+1

令人興奮的建築。深入的通用和功能性魔法。 – SerG 2017-09-11 13:10:42

3

這是我能想到的最接近的:

return a==1 ? "lalala" 
     : a==2 ? "blalbla" 
     : a==3 ? "lolollo" 
     : "default"; 
0

我們可以有一個我們可能需要從交換機內寫入的條件中返回值;讓我們說:

public void SomeMethod(SomeType enumType) 
{ 
    switch (enumType) 
    { 
     case a: 
      if (condition) 
      { 
       if (condition1 && condition2) 
       { 
        return true; 
       } 
      } 
      return false; 
      //break; break is actually not be required here if return used before break 
     case b: 
      if (condition) 
      { 
       if (condition3 && condition4) 
       { 
        return true; 
       } 
      } 
      return false; 
      // break; 
     default: 
      return false; 
      //break; 
    } 

    Public enum SomeType 
    { 
     a, 
     b, 
     c, 
     d 
    } 
2

mapping solution看起來像Jordão酒店的解決方案,但它是更靈活和更短。

return a 
    .Map(1,"lalala") 
    .Map(2,"blabla") 
    .Map(3,"lololo") 
    .Else(string.Empty); 

兩個參數也可以是一個函數:

return a 
    .Map(x => x <= 0, "lalala") 
    .Map(2, "blabla") 
    .Map(x => x >= 3, x => "lololo" + x.ToString()); // lololo3 etc. 
1

我創建了一個NuGet包(FluentSwitch)應該做你想做的。因此,您可以執行以下操作:

var result = myValue.Switch() 
    .When(1, "lalala") 
    .When(2, "blalbla") 
    .When(3, "lolollo") 
    .Else("default") 
    .Value();