2010-07-26 16 views
9

¿Cómo puedo combinar return y switch case declaraciones?de retorno y el interruptor de

Quiero algo así como

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

que sé de esta solución

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

Pero quiero usar sólo el operador return.

+0

AFAIK, el cambio no devuelve ningún valor, por lo que su uso es imposible. ¿Y por qué quieres hacer eso? – SWeko

Respuesta

19

switch y return No es posible combinar esa manera, porque es una declaración switch, no una expresión (es decir, que no devuelve un valor).
Si realmente desea utilizar un solo return, usted podría hacer un diccionario para mapear la variable interruptor para devolver valores:

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

que normalmente hago de esta manera:

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

¿Y por qué es superior a la salida anticipada, que tiene menos código y menos variables? –

+7

Esto NO es superior, pero la pregunta era tener solo una declaración de devolución y esa es la manera de tener solo una. – Oliver

15

creo que esta solución es la más lisa y llana, y que sin duda debe usarlo:

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

Pero, ya que preguntas por una return, que podría utilizar esta pequeña clase de fluidez:

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

Para crear un código como éste:

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

Por desgracia, los parámetros de tipo no podía deducirse por el compilador, y se siente un poco torpe. El Default disparará la evaluación del "interruptor", y debe ser la última llamada al método de la cadena. Tenga en cuenta que siempre se necesita un valor por defecto, ya que ha convertido en una expresión switch.

ACTUALIZACIÓN: Puede resolver el problema de la inferencia de tipos y unidad al usuario a hacer lo correcto con este código:

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

} 

El resultado es este agradable,, interfaz fluida con seguridad de tipos; donde en cada paso que sólo tendrá la opción correcta de métodos para llamar (por ejemplo, después de ThenCase):

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

Esto es genial, Jordao, pero tendría más sentido tener métodos como parámetros para los Thens (podrían ser anónimos). Como una declaración de caso normal. Puede tener varias líneas de código en una declaración de caso. Entonces, podrías decir int x = b + c * d; return "La respuesta es" + a.ToString(); por ejemplo. De todos modos, tendría que ser un método que devuelva el mismo tipo de objeto que a (en la cláusula On). ¿Tener sentido? – vbullinger

+1

@vbullinger: sí, tiene mucho sentido. De hecho, eso es exactamente lo que empecé a hacer hace algún tiempo, pero en realidad no terminé. –

+1

Construcción alucinante. Profunda magia genérica y funcional. – SerG

3

Esto es lo más cerca que puedo pensar:

return a==1 ? "lalala" 
     : a==2 ? "blalbla" 
     : a==3 ? "lolollo" 
     : "default"; 
0

Podemos tener uno caso de uso donde podemos necesitar devolver el valor de la condición escrita dentro del interruptor; digamos:

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

Mi mapping solution se parece a la solución de Jordão pero es más flexible y más corto.

return a 
    .Map(1,"lalala") 
    .Map(2,"blabla") 
    .Map(3,"lololo") 
    .Else(string.Empty); 

Ambos argumentos también pueden ser una función:

return a 
    .Map(x => x <= 0, "lalala") 
    .Map(2, "blabla") 
    .Map(x => x >= 3, x => "lololo" + x.ToString()); // lololo3 etc. 
1

He creado un paquete Nuget (FluentSwitch) que debe hacer lo que quiera. Por lo tanto, puede hacer lo siguiente:

var result = myValue.Switch() 
    .When(1, "lalala") 
    .When(2, "blalbla") 
    .When(3, "lolollo") 
    .Else("default") 
    .Value(); 
Cuestiones relacionadas