Combine return and switch

后端 未结 12 2067
长情又很酷
长情又很酷 2021-02-03 22:15

How can I combine return and switch case statements?

I want something like

return switch(a)
       {
          case 1:\"lalala         


        
12条回答
  •  陌清茗
    陌清茗 (楼主)
    2021-02-03 22:28

    I believe that this solution is the most straighforward one, and you should definitely use it:

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

    But, since you asked for one return, you could use this little fluent class:

    public class Switch {
      TElement _element;
      TElement _currentCase;
      IDictionary _map = new Dictionary();
    
      public Switch(TElement element) { _element = element; }
      public Switch Case(TElement element) {
        _currentCase = element;
        return this;
      }
      public Switch 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;
      }
    }
    

    To create code like this:

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

    Unfortunately, the type parameters could not be inferred by the compiler, and it feels a bit clumsy. The Default will trigger the evaluation of the "switch", and must be the last method call in the chain. Note that you always need a default value, since you've turned switch into an expression.

    UPDATE: You can solve the type inference problem and drive the user to do the right thing with this code:

    public static class Switch {
    
      public static SwitchBuilder.CaseBuilder On(TElement element) {
        return new SwitchBuilder(element).Start();
      }
    
      public class SwitchBuilder {
        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.CaseBuilder Then(TResult result) {
          return new SwitchBuilder(
            _element,
            _firstCase,
            result).Start();
        }
        public class CaseBuilder {
          internal SwitchBuilder Switch { get; set; }
          public ThenBuilder Case(TElement element) {
            return Switch.Case(element);
          }
        }
        public class ThenBuilder {
          internal SwitchBuilder Switch { get; set; }
          public SwitchBuilder.CaseBuilder Then(TResult result) {
            return Switch.Then(result);
          }
        }
      }
    
      public class SwitchBuilder {
        TElement _element;
        TElement _currentCase;
        IDictionary _map = new Dictionary();
        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 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 Switch { get; set; }
          public CaseBuilder Then(TResult result) {
            return Switch.Then(result);
          }
        }
      }
    
    }
    

    The result is this nice, type-safe, fluent interface; where at each step you'll only have the right choice of methods to call (e.g. Then after Case):

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

提交回复
热议问题