Frage

Kann ich erreichen

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

statt

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

War es hilfreich?

Lösung

Nein, Sie tun können:

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

, wenn Sie die LINQ Erweiterungen zur Verfügung, aber das ist kaum eine Verbesserung.


Als Reaktion auf den Kommentar über die Leistung, hier einige grundlegende Timing-Code. Beachten Sie, dass der Code muss mit einem kritischen Auge betrachtet werden, könnte ich die Dinge hier gemacht haben, dass die Timings Skew.

Die Ergebnisse zuerst:

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

Alle wurde der Code zweimal ausgeführt und nur nr passieren. 2 wurde berichtet, JITting Overhead aus der Gleichung zu entfernen. Beiden Ausweise Art der Überprüfung eine Million Mal ausgeführt und ausgeführt es sowohl in dem das Element zu finden war eines der Elemente zu finden in (das heißt, die if-Anweisung würde seinen Block ausführen), und einmal, wo das Element nicht (der Block würde nicht ausführen). Die Zeitpunkte der einzelnen berichtet. Getestet habe ich sowohl ein vorgefertigter Array und eine, die jedes Mal gebaut wird, ist dieser Teil ich nicht sicher bin, wie viel der Compiler leitet und optimiert weg, es könnte ein Fehler hier sein.

Auf jeden Fall scheint es, dass ein Schalter-Anweisung, mit oder ohne die Zeichenfolge zuerst Internierung, gibt in etwa die gleichen Ergebnisse wie die einfache oder-Anweisung, die zu erwarten ist, während der Array-Lookup viel mehr ist kostspielig, was erwartet wurde mir auch.

Bitte basteln mit dem Code und korrekt (oder Kommentar) es, wenn es Probleme gibt.

Und hier ist der Quellcode, ziemlich lang:

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

Andere Tipps

Nun, in der Nähe von, dass Sie erhalten können, ist:

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

Um mein Wissen, das keine Option ist.

können Sie reguläre Ausdrücke verwenden:

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

Wenn der Inhalt von „a“ kann länger sein als ein Zeichen verwenden:

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

Nein, nicht mit dieser Syntax. Aber es gibt viele Optionen, die codieren.

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

Vielleicht könnten Sie einige Betreiber Überlastung tun und Ihre Syntax zum Laufen bringen, aber das hängt davon ab, was Sie erreichen wollen und sind schwer von Ihrem einfachen Beispiel zu erzählen.

Sie können in bestimmten Situationen. Nämlich gekennzeichnet Aufzählungen:

[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

entspricht:

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

Der Grund dafür hat mit Bitmasken zu tun. Binär

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

Also, wenn wir verwenden die | Betreiber, machen wir eine Bit-für-Bit-Vergleich für alle 1en in der Spalte suchen und kopieren Sie sie in das Ergebnis. Wenn es keine 1en in der Spalte befindet, kopieren Sie ein 0.

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

Dann, wenn wir den Operator & anwenden, suchen wir nach 1 ist in allen Zeilen in jeder Spalte, bevor Sie ein 1 zu kopieren.

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

Welche> 0 ist, so gibt true zurück.

Seltsamerweise ist dies der effizienteste Weg, es zu tun, da es Ihnen einen numerischen Vergleich spart (>) und einen logischen Operator (||), die alle diese Phantasie Kurzschluss hat und so weiter.

Nein, das ist nicht, wie das oder Operator (||) arbeitet in C #.

Eine alternative Lösung, obwohl es den Code weniger lesbar macht, ist eine Funktion zu erstellen, die für den Wert überprüfen Sie wollen, etwas Ähnliches wie:

public static bool Any(object a, params object[] b)
{
    foreach(object item in b)
    {
        if(a == b)
        {
            return true;
        }
    }
    return false;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top