How can I combine return
and switch case
statements?
I want something like
return switch(a)
{
case 1:\"lalala
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");