2010-07-26 65 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();