Reputation: 71228
Is there another way to write something like this:
if (a == x || a == y || a == z)
One way that I found is doing it like this:
if( new [] {x,y,z}.Contains(a))
Are there other good ways?
Upvotes: 28
Views: 17576
Reputation: 81513
Fun fact, as of C#9 this is possible
var c ='b';
if (c is 'a' or 'b' or 'c')
Console.WriteLine("yes");
Which compiles to
if (c == 'a' || c == 'b' || c == 'c')
{
Console.WriteLine("yes");
}
Or you can get more creative
if (c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z') or '.' or ',')
Console.WriteLine("yes");
Which would roughly compile to (according to sharp io)
if (c >= 'a')
{
if (c <= 'z')
{
goto IL_0025;
}
}
else if (c >= 'A')
{
if (c <= 'Z')
{
goto IL_0025;
}
}
else if (c == ',' || c == '.')
{
goto IL_0025;
}
bool flag = false;
goto IL_002b;
IL_0025:
flag = true;
goto IL_002b;
IL_002b:
if (flag)
{
Console.WriteLine("yes");
}
Or use it in a switch
switch (c)
{
case 'a' or 'b' or 'c':
Console.WriteLine("yes");
break;
}
Upvotes: 4
Reputation: 7247
Consider a case where a == x, and y and z are slow-to-evaluate, expensive functions.
if(a == x || a == y || a == z)
you have the benefit of the short-circuit ||
-operator, so you y and z won't be evaluated. new[] { x, y, z }
- y and z will be evaluated every time. The 'trick' with .Contains()
would be more useful if there was an elegant syntax to create lazy-evaluated sequence (IEnumerable<T>
). i.e. something like yield return x; yield return y;...
, but inlined and shorter.
Upvotes: 5
Reputation: 11591
For instance, your logic is like that:
if(a==x || a== y|| a==z)
{
DoSomething();
}
else
{
DoOtherThings();
}
will equivalent to:
if(a!=x&& a != y && a!= z)
{
DoOtherThings();
}
else
{
DoSomething();
}
Cheers.
Upvotes: 0
Reputation: 10350
Your solution to rewrite it as
if( new [] {x,y,z}.Contains(a))
is not a good move.
You've take a simple efficient logical operation, which every programmer easily understands and which contains short-circuiting logic to speed it up and instead you've produced code that requires a moment to understand and which is considerably less efficient.
Sometimes your fellow engineers will prefer it if you don't try to be "clever"!
Upvotes: 6
Reputation: 129802
I often use an extension method that mimics SQLs IN
:
public static bool IsIn<T>(this T obj, params T[] collection) {
return collection.Contains(obj);
}
That way I can do
if(a.IsIn(b, c, d)) { ... }
Upvotes: 64
Reputation: 17752
Why would you need yet another way? Since it isn't a matter of functionality, I would guess the point is to improve readability.
If you have a few variables with meaningful names, it would be more readable to just compare by using ==
. If you have more, you can use Contains
against a list as in your other sample.
Yet another way would be comparing against enum flags:
[Flags]
public enum Size
{
Small = 1,
Medium = 2,
Large = 4
}
And then to find out if mySize
is in Small
or Medium
:
selectedSizes = Size.Small | Size.Medium;
mySize = Size.Small;
if (mySize & selectedSizes)
{
...
}
Upvotes: 2
Reputation: 71080
So, you want to replace a simple, efficent language construct that contains short-circuit optimisations into something much slower that has the potential for throwing exceptions?
However, if the items you want to compare against are not fixed in quantity, i.e. at run time it could be t,u,v,w,x,y,z,etc..., then the Collection.Contains method is the only option, but then you'd be passing collection objects around rather than individual values and so there's little memory allocation ovrehead.
If you've got a large number of items to compare 'a' against, but the items are not dynamic at run time then a switch statement might be a better fit.
Upvotes: 3
Reputation: 57202
Just for fun:
using System;
static class Program {
static bool In(this object obj, params object[] values) {
foreach (object value in values) {
if (obj.Equals(value)) {
return true;
}
}
return false;
}
static void Main(string[] args) {
bool test1 = 3.In(1, 2, 3);
bool test2 = 5.In(1, 2, 3);
}
}
But I really think that the best way is to write the plain check
if(a == x || a == y || a == z)
As everybody will understand immediately what it does.
Upvotes: 6
Reputation: 11477
You have the classic switch statement :
switch(a) {
case x:
case y:
case z:
// Do stuff
break;
}
Upvotes: 12