No, you can do:
if (new[] { "b", "c" }.Contains(a))
if you have LINQ extensions, but this is unlikely to improve.
In response to a performance comment, here are a few basic time codes. Please note that the code must be viewed with a critical eye, I could do something here that distorts the timings.
First results:
||, 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 code was executed twice, and only pass nr. 2, to remove JITting overhead from the equation. Both passes performed each type of verification one million times and performed it as where the element to search for was one of the elements to search for it (that is, the if statement executed its block), and once when the element was not (the block will not be executed ) The timings of each of them are reported. I tested both the ready-made array and the one that is built every time, this part, I'm not sure how much the compiler outputs and optimizes away, there may be a drawback.
In any case, it seems that using the switch statement with or without string interpolation at first gives roughly the same results as the simple or -operator that you should expect, while array lookups are much more expensive, which I also expected.
Please change the code and correct (or comment on) it if problems arise.
And here is the source code, quite 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);