Usa string.Contiene() con interruptor()


Estoy haciendo una aplicación de C # donde uso

if ((message.Contains("test")))
{
   Console.WriteLine("yes");
} else if ((message.Contains("test2"))) {
   Console.WriteLine("yes for test2");
}

¿Habría alguna manera de cambiar a switch() las declaraciones if()?

Author: Karl Kieninger, 2011-08-24

7 answers

Puede hacer la comprobación al principio y luego usar el interruptor como desee.

Por ejemplo:

string str = "parameter"; // test1..test2..test3....

if (!message.Contains(str)) return ;

Entonces

switch(str)
{
  case "test1" : {} break;
  case "test2" : {} break;
  default : {} break;
}
 11
Author: shenhengbin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-07 09:45:41

No, la instrucción switch requiere constantes de tiempo de compilación. La instrucción message.Contains("test") puede evaluar true o false dependiendo del mensaje, por lo que no es una constante, por lo que no se puede usar como 'case' para la instrucción switch.

 31
Author: Teoman Soygul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-24 12:43:05

Si solo quieres usar switch/case, puedes hacer algo como esto, pseudo-código:

    string message = "test of mine";
    string[] keys = new string[] {"test2",  "test"  };

    string sKeyResult = keys.FirstOrDefault<string>(s=>message.Contains(s));

    switch (sKeyResult)
    {
        case "test":
            Console.WriteLine("yes for test");
            break;
        case "test2":
            Console.WriteLine("yes for test2");
            break;
    }

Pero si la cantidad de claves es grande, puedes reemplazarla con un diccionario, así:

static Dictionary<string, string> dict = new Dictionary<string, string>();
static void Main(string[] args)
{
    string message = "test of mine";      

    // this happens only once, during initialization, this is just sample code
    dict.Add("test", "yes");
    dict.Add("test2", "yes2"); 


    string sKeyResult = dict.Keys.FirstOrDefault<string>(s=>message.Contains(s));

    Console.WriteLine(dict[sKeyResult]); //or `TryGetValue`... 
 }
 25
Author: Tigran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-07 17:56:44

Corrige la sintaxis final de la respuesta de [Mr.C].

Con el lanzamiento de VS2017RC y su soporte para C # 7 funciona de esta manera:

switch(message)
{
    case string a when a.Contains("test2"): return "no";
    case string b when b.Contains("test"): return "yes";
}

Debes encargarte del orden del caso ya que se elegirá la primera partida. Es por eso que "test2" se coloca antes de la prueba.

 13
Author: Lakedaimon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-02 14:16:40

Esto funcionará en C# 7. Al momento de escribir este artículo, aún no se ha publicado. Pero si entiendo esto correctamente, este código funcionará.

switch(message)
{
    case Contains("test"):
        Console.WriteLine("yes");
        break;
    case Contains("test2"):
        Console.WriteLine("yes for test2");
        break;
    default:
        Console.WriteLine("No matches found!");
}

Fuente: https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/

 5
Author: Mr. C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-15 18:42:54

Algunos swtich personalizados se pueden crear así. También permite la ejecución de múltiples casos

public class ContainsSwitch
{

    List<ContainsSwitch> actionList = new List<ContainsSwitch>();
    public string Value { get; set; }
    public Action Action { get; set; }
    public bool SingleCaseExecution { get; set; }
    public void Perform( string target)
    {
        foreach (ContainsSwitch act in actionList)
        {
            if (target.Contains(act.Value))
            {
                act.Action();
                if(SingleCaseExecution)
                    break;
            }
        }
    }
    public void AddCase(string value, Action act)
    {
        actionList.Add(new ContainsSwitch() { Action = act, Value = value });
    }
}

Llama así

string m = "abc";
ContainsSwitch switchAction = new ContainsSwitch();
switchAction.SingleCaseExecution = true;
switchAction.AddCase("a", delegate() { Console.WriteLine("matched a"); });
switchAction.AddCase("d", delegate() { Console.WriteLine("matched d"); });
switchAction.AddCase("a", delegate() { Console.WriteLine("matched a"); });

switchAction.Perform(m);
 2
Author: hungryMind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-25 07:39:20

Frente a este problema al determinar un entorno, se me ocurrió lo siguiente:

string ActiveEnvironment = localEnv.Contains("LIVE") ? "LIVE" : (localEnv.Contains("TEST") ? "TEST" : (localEnv.Contains("LOCAL") ? "LOCAL" : null));

De esa manera, si no puede encontrar nada en la cadena proporcionada que coincida con las condiciones "switch", se da por vencido y devuelve null. Esto podría modificarse fácilmente para devolver un valor diferente.

No es estrictamente un interruptor, más bien una sentencia if en cascada, pero es ordenada y funcionó.

 1
Author: 0xFF,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 13:02:44