Question

Puis-je atteindre

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

au lieu de

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

?

Était-ce utile?

La solution

Non, vous pouvez faire:

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

si vous disposez des extensions LINQ , ce n'est guère une amélioration.

En réponse au commentaire sur les performances, voici un code de synchronisation de base. Notez que le code doit être vu avec un œil critique, j'aurais peut-être fait des choses ici qui faussent les timings.

Les premiers résultats:

||, 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

Tout le code a été exécuté deux fois, et ne passez que n °. 2 a été rapporté, afin de supprimer les frais généraux JITting de l'équation. Les deux passes ont exécuté chaque type de vérification un million de fois, et l'ont exécuté à la fois lorsque l'élément à rechercher était l'un des éléments dans lesquels le trouver (c'est-à-dire que l'instruction if exécuterait son bloc), et une fois où l'élément n'était pas (le bloc ne s'exécuterait pas). Les horaires de chacun sont rapportés. J'ai testé à la fois un tableau pré-construit et un qui est construit à chaque fois. Cette partie, je ne sais pas combien de temps le compilateur déduit et optimise, il y a peut-être un défaut ici.

Quoi qu’il en soit, il semble que l’utilisation d’une instruction switch, avec ou sans interner d’abord la chaîne, donne à peu près les mêmes résultats que l’instruction or simple, ce à quoi on pouvait s’attendre, alors que la recherche de tableau est beaucoup plus complexe. coûteux, ce qui m’était aussi attendu.

Veuillez bricoler le code et le corriger (ou le commenter) en cas de problème.

Et voici le code source, plutôt long:

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

Autres conseils

Eh bien, le plus proche de ce que vous pouvez obtenir est:

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

À ma connaissance, cela n’est pas une option.

Vous pouvez utiliser des expressions régulières:

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

Si le contenu de " a " peut être plus long qu'un caractère, utilisez ceci:

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

Non, pas avec cette syntaxe. Mais il existe de nombreuses options pour coder cela.

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

Vous pourriez peut-être surcharger un opérateur et faire fonctionner votre syntaxe, mais cela dépend vraiment de ce que vous voulez atteindre et il est difficile de le dire à partir de votre exemple.

Vous pouvez dans certaines situations. Enumérations marquées:

[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

est équivalent à:

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

La raison en est liée aux masques de bits. En binaire,

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

Donc, quand on utilise le | opérateur, nous comparons petit à petit les 1 dans la colonne et les copions dans le résultat. S'il n'y a pas de 1 dans la colonne, vous copiez un 0.

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

Ensuite, lorsque nous appliquons le & amp; opérateur, nous recherchons des 1 dans toutes les lignes de chaque colonne avant de copier un 1.

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

Qui est > 0, retournant ainsi vrai.

Curieusement, c’est le moyen le plus efficace de le faire, car cela vous évite une comparaison numérique (>) et un opérateur logique (||), ce qui permet de faire tout ce qui est court-circuité ou autre.

Non, ce n'est pas ainsi que l'opérateur ou (||) fonctionne en C #.

Une autre solution, bien que rendant le code moins lisible, consiste à créer une fonction qui recherche la valeur souhaitée, similaire à:

public static bool Any(object a, params object[] b)
{
    foreach(object item in b)
    {
        if(a == b)
        {
            return true;
        }
    }
    return false;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top