2010-07-26 3 views
9

Как я могу объединить return и switch 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

ответ

19

switch и return не может объединить таким образом, потому что это 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

И почему это превосходит ранний выход, который имеет меньше кода и меньше переменных? –

+7

Это НЕ ВЫСОКО, но вопрос состоял в том, чтобы иметь только одно выражение return, и это способ иметь только один. – Oliver

15

Я считаю, что это решение является наиболее straighforward один, и вы должны обязательно использовать:

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

} 

В результате этот славный, типобезопасный, свободно интерфейс; где на каждом шагу вы будете иметь только правильный выбор методов для вызова (например, Then после Case):

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

Это замечательно, Jordao, но было бы разумнее иметь методы в качестве параметров для Thens (они могут быть анонимными). Как нормальный случай. Вы можете иметь несколько строк кода в case case. Итак, вы могли бы сказать int x = b + c * d; return «Ответ:« + a.ToString(); например. В любом случае, это должен был быть метод, который возвращает тот же тип объекта, что и (в предложении On). Имеют смысл? – vbullinger

+1

@vbullinger: да, это имеет смысл. Фактически, это именно то, что я начал делать некоторое время назад, но на самом деле не закончил. –

+1

Mind-blowing construction. Глубокая родовая и функциональная магия. – SerG

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 выглядит как решение Jordao, но она является более гибкой и короче.

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(); 
Смежные вопросы