OR operator in C#

19,796

Solution 1

No, you can do:

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

if you have the LINQ extensions available, but that's hardly an improvement.


In response to the comment about performance, here's some basic timing code. Note that the code must be viewed with a critical eye, I might have done things here that skew the timings.

The results first:

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

All the code was executed twice, and only pass nr. 2 was reported, to remove JITting overhead from the equation. Both passes executed each type of check one million times, and executed it both where the element to find was one of the elements to find it in (that is, the if-statement would execute its block), and once where the element was not (the block would not execute). The timings of each is reported. I tested both a pre-built array and one that is built every time, this part I'm unsure how much the compiler deduces and optimizes away, there might be a flaw here.

In any case, it appears that using a switch-statement, with or without interning the string first, gives roughly the same results as the simple or-statement, which is to be expected, whereas the array-lookup is much more costly, which to me was also expected.

Please tinker with the code, and correct (or comment) it if there's problems.

And here's the source code, rather 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" };
        }
    }
}

Solution 2

Well, the closest to that you can get is:

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

Solution 3

You can use Regular Expressions:

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

If the contents of "a" can be longer than one character use this:

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

Solution 4

To my knowledge that isn't an option.

Solution 5

No, not with that syntax. But there are many options to code that.

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

Maybe you could do some operator overloading and get your syntax working, but this really depends on what you want to achieve and is hard to tell from your simple example.

Share:
19,796
Saif Khan
Author by

Saif Khan

Updated on June 04, 2022

Comments

  • Saif Khan
    Saif Khan 6 months

    Can I achieve

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

    instead of

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

    ?

    • Darren Kopp
      Darren Kopp over 13 years
      ... don't you mean || operator?
    • Summer Sun
      Summer Sun over 13 years
      The | operator is not exclusively a binary operator in C#, it still has an important purpose: stackoverflow.com/questions/579352/calling-methods-inside-if‌​-c/…
    • Lasse V. Karlsen
      Lasse V. Karlsen over 13 years
      | is both logical and binary, depending on expression, but it evaluates both sides, so while the code wasn't the typical code, it was still correct.
    • Greg
      Greg over 13 years
      I've wished for this ability for a long time.
    • cregox
      cregox over 10 years
      I've wished for something similar. Just remove all quotes and there you go.
  • Nathan Ridley
    Nathan Ridley over 13 years
    The accepted answer is less code, but using a switch statement has less overhead I believe.
  • Lucas B
    Lucas B over 13 years
    I recommend this solution instead. First, it is more readable. Second, it has less overhead. Third, if the logic has to change in the future it is easier to maintain.
  • Kon
    Kon over 13 years
    Accepted answer might fit nicer on a single line, but this one doesn't allocate extra memory for an array.
  • Richard
    Richard over 13 years
    If the array is allocated statically, then performance test might be interesting (if time taken by the expression is long enough to be measured against the overhead of the timing).
  • Patrik Hägne
    Patrik Hägne over 13 years
    I would argue that the alternative given in the question - "if(a == "b" || a== "c")" - is the closest you can get and is - in my opinion - a way better solution than introducing the switch-statement.