Pregunta

¿Puedo lograr?

if (a == "b" || "c")

en lugar de

if (a == "b" || a== "c")

?

¿Fue útil?

Solución

No, puedes hacerlo:

if (new[] { "b", "c" }.Contains(a))

si tienes las LINQ disponibles, pero eso no es una mejora.


En respuesta al comentario sobre el rendimiento, aquí hay un código de tiempo básico. Tenga en cuenta que el código debe verse con un ojo crítico, podría haber hecho cosas aquí que sesgan los tiempos.

Los resultados primero:

||, not found: 26 ms
||, found: 8 ms
array.Contains, not found: 1407 ms
array.Contains, found: 1388 ms
array.Contains, inline array, not found: 1456 ms
array.Contains, inline array, found: 1427 ms
switch-statement, not interned, not found: 26 ms
switch-statement, not interned, found: 14 ms
switch-statement, interned, not found: 25 ms
switch-statement, interned, found: 8 ms

Todo el código se ejecutó dos veces, y solo se pasa nr. 2 se informó, para eliminar la sobrecarga JITting de la ecuación. Ambos pases ejecutaron cada tipo de verificación un millón de veces y lo ejecutaron donde el elemento a encontrar fue uno de los elementos para encontrarlo (es decir, la instrucción if ejecutaría su bloque), y una vez donde el elemento no estaba (El bloque no se ejecutaría). Se informa de los tiempos de cada uno. Probé tanto una matriz preconstruida como una que se construye cada vez, esta parte no estoy seguro de cuánto deduce y optimiza el compilador, podría haber una falla aquí.

En cualquier caso, parece que el uso de una instrucción de cambio, con o sin internar primero la cadena, proporciona aproximadamente los mismos resultados que la instrucción simple o, lo que es de esperar, mientras que la búsqueda de matrices es mucho más costoso, que a mí también se esperaba.

Pruebe el código y corríjalo (o coméntelo) si hay problemas.

Y aquí está el código fuente, bastante largo:

using System;
using System.Linq;
using System.Diagnostics;
namespace StackOverflow826081
{
    class Program
    {
        private const Int32 ITERATIONS = 1000000;
        static void Main()
        {
            String a;
            String[] ops = CreateArray();
            Int32 count;
            Stopwatch sw = new Stopwatch();
            Int32 pass = 0;
            Action<String, Int32> report = delegate(String title, Int32 i)
            {
                if (pass == 2)
                    Console.Out.WriteLine(title + ": " + sw.ElapsedMilliseconds + " ms");
            };

            for (pass = 1; pass <= 2; pass++)
            {
                #region || operator

                a = "a";
                sw.Start();

                count = 0;
                for (Int32 index = 0; index < ITERATIONS; index++)
                {
                    if (a == "b" || a == "c")
                    {
                        count++;
                    }
                }
                sw.Stop();
                report("||, not found", count);
                sw.Reset();

                a = "b";
                sw.Start();

                count = 0;
                for (Int32 index = 0; index < ITERATIONS; index++)
                {
                    if (a == "b" || a == "c")
                    {
                        count++;
                    }
                }
                sw.Stop();
                report("||, found", count);
                sw.Reset();

                #endregion

                #region array.Contains

                a = "a";
                sw.Start();

                count = 0;
                for (Int32 index = 0; index < ITERATIONS; index++)
                {
                    if (ops.Contains(a))
                    {
                        count++;
                    }
                }
                sw.Stop();
                report("array.Contains, not found", count);
                sw.Reset();

                a = "b";
                sw.Start();

                count = 0;
                for (Int32 index = 0; index < ITERATIONS; index++)
                {
                    if (ops.Contains(a))
                    {
                        count++;
                    }
                }
                sw.Stop();
                report("array.Contains, found", count);
                sw.Reset();

                #endregion           

                #region array.Contains

                a = "a";
                sw.Start();

                count = 0;
                for (Int32 index = 0; index < ITERATIONS; index++)
                {
                    if (CreateArray().Contains(a))
                    {
                        count++;
                    }
                }
                sw.Stop();
                report("array.Contains, inline array, not found", count);
                sw.Reset();

                a = "b";
                sw.Start();

                count = 0;
                for (Int32 index = 0; index < ITERATIONS; index++)
                {
                    if (CreateArray().Contains(a))
                    {
                        count++;
                    }
                }
                sw.Stop();
                report("array.Contains, inline array, found", count);
                sw.Reset();

                #endregion

                #region switch-statement

                a = GetString().Substring(0, 1); // avoid interned string
                sw.Start();

                count = 0;
                for (Int32 index = 0; index < ITERATIONS; index++)
                {
                    switch (a)
                    {
                        case "b":
                        case "c":
                            count++;
                            break;
                    }
                }
                sw.Stop();
                report("switch-statement, not interned, not found", count);
                sw.Reset();

                a = GetString().Substring(1, 1); // avoid interned string
                sw.Start();

                count = 0;
                for (Int32 index = 0; index < ITERATIONS; index++)
                {
                    switch (a)
                    {
                        case "b":
                        case "c":
                            count++;
                            break;
                    }
                }
                sw.Stop();
                report("switch-statement, not interned, found", count);
                sw.Reset();

                #endregion                      

                #region switch-statement

                a = "a";
                sw.Start();

                count = 0;
                for (Int32 index = 0; index < ITERATIONS; index++)
                {
                    switch (a)
                    {
                        case "b":
                        case "c":
                            count++;
                            break;
                    }
                }
                sw.Stop();
                report("switch-statement, interned, not found", count);
                sw.Reset();

                a = "b";
                sw.Start();

                count = 0;
                for (Int32 index = 0; index < ITERATIONS; index++)
                {
                    switch (a)
                    {
                        case "b":
                        case "c":
                            count++;
                            break;
                    }
                }
                sw.Stop();
                report("switch-statement, interned, found", count);
                sw.Reset();

                #endregion
            }
        }

        private static String GetString()
        {
            return "ab";
        }

        private static String[] CreateArray()
        {
            return new String[] { "b", "c" };
        }
    }
}

Otros consejos

Bueno, lo más cercano a lo que puedes obtener es:

switch (a) {
   case "b":
   case "c":
      // variable a is either "b" or "c"
      break;
}

Que yo sepa, eso no es una opción.

Puedes usar expresiones regulares:

if(Regex.IsMatch(a, "b|c"))

Si el contenido de " a " puede ser más largo que un carácter usa esto:

if(Regex.IsMatch(a, "^(b|c)<*>quot;))

No, no con esa sintaxis. Pero hay muchas opciones para codificar eso.

if ("bc".Contains(a)) { } // Maybe check a.Length == 1, too.

if ((a[0] & 0x62) == 0x62) { } // Maybe check a.Length == 1, too.

if (new String[] { "b", "c" }.Contains(a)) { }

Tal vez podría sobrecargar a un operador y hacer que su sintaxis funcione, pero esto realmente depende de lo que quiere lograr y es difícil decirlo con su simple ejemplo.

Puedes en ciertas situaciones. A saber, enumeraciones marcadas:

[Flags]
enum MyEnum {
    None = 0,
    A = 1,
    B = 2,
    C = 4,
    D = 8
}

//...

MyEnum a = MyEnum.B

if((a & (MyEnum.B | MyEnum.C)) > 0)
    // do something

es equivalente a:

if((a & MyEnum.B) > 0 || (a & MyEnum.C) > 0)
    // do something

El motivo de esto tiene que ver con las máscaras de bits. En binario,

None = 00000
A    = 00001
B    = 00010
C    = 00100
D    = 01000

Entonces cuando usamos el | operador, hacemos una comparación bit a bit buscando cualquier 1 en la columna y los copiamos en el resultado. Si no hay 1 en la columna, copie un 0.

  B 00010
& C 00100
---------
    00110

Luego, cuando aplicamos el & amp; operador, buscamos 1 en todas las filas de cada columna antes de copiar un 1.

  (B & C) 00110
& (a = B) 00010
---------------
          00010

que es > 0, volviendo así verdadero.

Por extraño que parezca, esta es la forma más eficiente de hacerlo, ya que le ahorra una comparación numérica (>) y un operador lógico (||), que hace todo ese corto circuito de fantasía y todo eso.

No, no es así como funciona el operador or (||) en C #.

Una solución alternativa, aunque hace que el código sea menos legible, es crear una función que verifique el valor que desea, algo similar a:

public static bool Any(object a, params object[] b)
{
    foreach(object item in b)
    {
        if(a == b)
        {
            return true;
        }
    }
    return false;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top