结合返回和切换

Nei*_*ir0 12 c# switch-statement switch-expression

我该如何结合returnswitch case陈述?

我想要类似的东西

return switch(a)
       {
          case 1:"lalala"
          case 2:"blalbla"
          case 3:"lolollo"
          default:"default" 
       };
Run Code Online (Sandbox Code Playgroud)

我知道这个解决方案

switch(a)
{
    case 1: return "lalala";
    case 2: return "blalbla";
    case 3: return "lolollo";
    default: return "default";
}
Run Code Online (Sandbox Code Playgroud)

但我想只使用return运营商.

tza*_*man 22

switch并且return不能以这种方式组合,因为它switch是一个语句,而不是一个表达式(即,它不返回一个值).
如果你真的只想使用一个return,你可以创建一个Dictionary来映射switch变量以返回值:

var map = new Dictionary<int, string>() 
{
    {1, "lala"}, 
    {2, "lolo"}, 
    {3, "haha"}, 
};
string output;
return map.TryGetValue(a, out output) ? output : "default";
Run Code Online (Sandbox Code Playgroud)

  • @Neir0 可能最好将接受的答案切换为另一个! (3认同)

Jor*_*dão 19

我相信这个解决方案是最直接的解决方案,你绝对应该使用它:

switch(a) { 
  case 1: return "lalala"; 
  case 2: return "blabla"; 
  case 3: return "lololo"; 
  default: return "default"; 
} 
Run Code Online (Sandbox Code Playgroud)

但是,既然你要求一个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;
  }
}
Run Code Online (Sandbox Code Playgroud)

要创建这样的代码:

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

不幸的是,编译器无法推断类型参数,感觉有点笨拙.该Default会触发"开关"的评价,而且必须是在链中的最后一个方法调用.请注意,您始终需要一个默认值,因为您已经变成switch了一个表达式.

更新:您可以解决类型推断问题并驱动用户使用以下代码执行正确的操作:

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);
      }
    }
  }

}
Run Code Online (Sandbox Code Playgroud)

结果是这个漂亮,类型安全,流畅的界面; 在每个步骤中,您只能选择正确的方法(例如,Then之后Case):

return Switch.On(a)
  .Case(1).Then("lalala")
  .Case(2).Then("blabla")
  .Case(3).Then("lololo")
  .Default("default");
Run Code Online (Sandbox Code Playgroud)

  • 这很棒,Jordao,但将方法作为Thens的参数更有意义(它们可以是匿名的).像正常的案例陈述一样.您可以在case语句中包含多行代码.所以,你可以说int x = b + c*d; 返回"答案是"+ a.ToString(); 例如.无论如何,它必须是一个返回与(在On子句中)相同类型的对象的方法.合理? (2认同)

Oli*_*ver 15

我通常这样做:

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;
Run Code Online (Sandbox Code Playgroud)

  • 这不是优越的,但问题是只有一个返回语句,这是只有一个的方式. (10认同)

Dan*_* Z. 7

实际上,可以使用以C#8开头的开关表达式来实现。

return a switch
    {
        1 => "lalala",
        2 => "blalbla",
        3 => "lolollo",
        _ => "default"
    };
Run Code Online (Sandbox Code Playgroud)

切换表达式

这里有一些语法改进:

  • 该变量位于switch关键字之前。不同的顺序使视觉上很容易将switch表达式与switch语句区分开。
  • case和:元素替换为=>。更加简洁直观。
  • 默认情况下用_替换。
  • 主体是表达式,而不是语句。

有关更多信息和示例,请查看Microsoft的C#8新增功能

  • 我等了10年 (2认同)

Mar*_*ade 6

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

return    a==1 ? "lalala"
        : a==2 ? "blalbla"
        : a==3 ? "lolollo"
        : "default";
Run Code Online (Sandbox Code Playgroud)


Ahm*_*ıcı 5

switch(a)
{
    case 1: return "lalala";
    case 2: return "blalbla";
    case 3: return "lolollo";
    default: return "default";
}
Run Code Online (Sandbox Code Playgroud)


Sib*_*enu 5

有了新功能C# 8,您可以将return和结合使用switch。新switch的东西真可爱。

public static RGBColor FromRainbow(Rainbow colorBand) =>
    colorBand switch
    {
        Rainbow.Red    => new RGBColor(0xFF, 0x00, 0x00),
        Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),
        Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),
        Rainbow.Green  => new RGBColor(0x00, 0xFF, 0x00),
        Rainbow.Blue   => new RGBColor(0x00, 0x00, 0xFF),
        Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),
        Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),
        _              => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand))
    };
Run Code Online (Sandbox Code Playgroud)

等效的旧开关如下。

public static RGBColor FromRainbowClassic(Rainbow colorBand)
{
    switch (colorBand)
    {
        case Rainbow.Red:
            return new RGBColor(0xFF, 0x00, 0x00);
        case Rainbow.Orange:
            return new RGBColor(0xFF, 0x7F, 0x00);
        case Rainbow.Yellow:
            return new RGBColor(0xFF, 0xFF, 0x00);
        case Rainbow.Green:
            return new RGBColor(0x00, 0xFF, 0x00);
        case Rainbow.Blue:
            return new RGBColor(0x00, 0x00, 0xFF);
        case Rainbow.Indigo:
            return new RGBColor(0x4B, 0x00, 0x82);
        case Rainbow.Violet:
            return new RGBColor(0x94, 0x00, 0xD3);
        default:
            throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand));
    };
}
Run Code Online (Sandbox Code Playgroud)

您可以在此处阅读有关此功能的信息