23

In C#, instead of doing if(index == 7 || index == 8), is there a way to combine them? I'm thinking of something like if(index == (7, 8)).

Andrew
  • 2,519
  • 6
  • 29
  • 46
  • What are you trying to accomplish? Making it easier to read, or more succinct? – agent-j Jun 17 '11 at 18:37
  • Both. Having a lot of equality conditions would take up more room than it should. A more compact version would give cleaner code, without losing readability. – Andrew Jun 17 '11 at 18:42
  • 1
    Duplicate of [C#. Do if( a == (b or c or d)). Is it possible?](http://stackoverflow.com/questions/3244333/c-do-if-a-b-or-c-or-d-is-it-possible) – Danko Durbić Jun 18 '11 at 09:05
  • 1
    Duplicate of [Can I compress an if statement using linq in C#?](http://stackoverflow.com/questions/2007003/can-i-compress-an-if-statement-using-linq-in-c/2007118) – Callum Rogers Jun 18 '11 at 17:38

9 Answers9

55

You can accomplish this with an extension method.

public static bool In<T>(this T obj, params T[] collection) {
   return collection.Contains(obj);
}

Then...

if(index.In(7,8))
{
    ...
}
48klocs
  • 6,073
  • 3
  • 27
  • 34
  • +1 This is extremely nice. I don't how overkill that is, but it's fancy! Wish I could upvote twice – Adriano Carneiro Jun 17 '11 at 18:38
  • 1
    +1 for very cool solution. Probably overkill (especially for a list of 2 numbers), but very cool. – Coeffect Jun 17 '11 at 18:41
  • 1
    This is definitively going into my ext. methods lib – Adriano Carneiro Jun 17 '11 at 18:43
  • Interesting solution, but seems potentially expensive for a lot of scenarios. – kabuko Jun 18 '11 at 04:26
  • 3
    Whilst this is a clever solution I can't help thinking it is a) overkill and overly expensive and b) doesn't address the underlying problem of *why* there are so many "magic number" comparisons going on in OPs code. – Dan Diplo Jun 18 '11 at 10:06
  • 1
    +1 nice solution. Everyone worried about overkill and the use of literals should consider the possibility that the OP gave a simplistic example of a general issue. Also, performance can be measured and adjusted if issues are found, but I would suspect this routine would perform within acceptable range for the vast majority of use. – JeremyDWill Jun 18 '11 at 19:38
9

You could put the values that you need to compare into an inline array and use a Contains extension method. See this article for starters.

Several snippets demonstrating the concept:

int index = 1;
Console.WriteLine("Example 1: ", new int[] { 1, 2, 4 }.Contains(index));

index = 2;
Console.WriteLine("Example 2: ", new int[] { 0, 5, 3, 4, 236 }.Contains(index));

Output:

Example 1: True
Example 2: False
Paul Sasik
  • 79,492
  • 20
  • 149
  • 189
  • 2
    I like this better than the accepted answer because it's clear. Still I'd look at this list of constants in my code and wonder if they couldn't be extracted into some other system. Just a bad code smell to have some arbitrary list of numbers (or even enums) – Bill K Jun 18 '11 at 07:11
  • @Bill K: I agree that my snippet, as it stands, would not be good for production. It is meant to show the concept as clearly as possible. For production I would suggest a constant array of values with a meaningful name. – Paul Sasik Jun 18 '11 at 13:23
  • An array of values like that suggests some kind of permanence--whenever you have a list of numbers like that there is a really good chance they will change and should probably be data. If it was an array like "validCodes" read in from a file--that suddenly gets interesting but your solution is perfect in that case. – Bill K Jun 18 '11 at 19:48
3

There is no way, in the current C# syntax set, to combine multiple right-hand-side operands to be passed to a single binary operator to the best of my knowledge.

Jeff Hubbard
  • 9,822
  • 3
  • 30
  • 28
  • Not an answer, not helpful in finding an answer. – SQLMason Jun 17 '11 at 19:16
  • @Dan Andrews So "no, this is not possible" is not an answer? I'm fairly confident that there is no way to combine a single comparison operator using multiple operands syntax-wise. Your answer above does not help when the things being compared are of different types. – Jeff Hubbard Jun 17 '11 at 20:29
  • @Jeff: I'm sorry that you're upset. But your answer did not help find a solution nor did it suggest one. You should have just commented. Your comment about using multiple operands shows that you didn't understand the question. – SQLMason Jun 17 '11 at 20:35
  • 2
    First, I'm not upset. I understand *why* you say my answer is not an answer, and I disagree with your logic. There's a difference there. However, your assumption that I didn't understand the question--which I did perfectly well--is invalid. There is no way, in the current C# syntax set, to combine multiple RHS operands to be passed to a single binary operator to the best of my knowledge. There are some very specific workarounds for very specific types, but that isn't useful in the long run. I'll edit my answer to be more clear on exactly what I mean. – Jeff Hubbard Jun 17 '11 at 21:34
  • 2
    The problem is... that there are a few answers already. It may not be technically possible in a "x == 6,7" format BUT there are answers to the questions intent. "That isn't possible because FOO, but here's how you do what your asking.. do BAR" would have been a good answer. "That's not possible" is a crappy answer that doesn't help solve the problem. – WernerCD Jun 18 '11 at 15:47
  • That was why I revised my answer to be as specific as possible. – Jeff Hubbard Jun 19 '11 at 06:04
2

Write your own extension methods so you can write

if (index.Between(7, 8)) {...}

where Between is defined as:

    public static bool Between (this int a, int x, int y)
    {
        return a >= x && a <= y;
    }
Saurabh Gokhale
  • 53,625
  • 36
  • 139
  • 164
Tundey
  • 2,926
  • 1
  • 23
  • 27
  • I guess you have a +4 for mentioning extension method since your solution doesn't do what the question wants. :) – SQLMason Jun 17 '11 at 19:49
  • While this extension method could certainly be useful, the question asks how to combine multiple conditions, not how to determine if the value falls within a certain range. – Jeromy Irvine Jun 18 '11 at 00:35
2

You could use this:

 if (new List<int>() { 7, 8 }.Contains(index))
Saurabh Gokhale
  • 53,625
  • 36
  • 139
  • 164
Ed Bayiates
  • 11,060
  • 4
  • 43
  • 62
  • To make it in less chars, you could do it `if (new int[] { 7, 8 }.Contains(index))` – Adriano Carneiro Jun 17 '11 at 18:36
  • 2
    Instead of being brief and mentioning how over-exaggerated the use of a list to satisfy checking two numbers is, I'm going to write a fairly lengthy paragraph, requiring more effort to read, just to convey the same point: that using a list is not, in any way, more brief, concise, or efficient than just comparing the variable in two conditions. – Brad Christie Jun 17 '11 at 18:36
  • @Brad: he could have 20 conditions. Why bother writing all of that out? – Ed Bayiates Jun 17 '11 at 18:37
  • 1
    @AresAvatar: Because a list is resource over-kill. And, in cases of multiple-number comparisons, there exists case statements. -- EDIT: I'm not going to down-vote because it is a viable option, it's just the essence of using a sledge hammer to hang a picture kind of over-kill. – Brad Christie Jun 17 '11 at 18:38
  • @Brad: whether it's overkill is a decision best made by the programmer, not by you for this one example, and one could also make the list (or array) static. We're constructively answering the poster and you aren't. – Ed Bayiates Jun 17 '11 at 18:41
  • @Brad, I don't disagree with your general premise, but I will disagree that a *long* list of values isn't more readable or convenient in an array or list rather than string of or'd if conditionals or case statements. At any rate, this comes down to a tradeoff of convenience and possibility readability vs. creating additional garbage. (In the example of just two values, by all means, use the `or`). – Anthony Pegram Jun 17 '11 at 18:42
  • @AresAvatar: Again, I'm not saying it's not viable, I'm merely saying it's too much. But, if you're going all-out, I feel a class should be made for scnarios such as this so the [user] can call `(new NumberChecker(index)).Matches(7,8)`. – Brad Christie Jun 17 '11 at 18:47
2
switch (GetExpensiveValue())
{
case 7: case 8:
   // do work
   break;
}

This obviously takes more code, but it may save you from evaluating a function a bunch of times.

agent-j
  • 27,335
  • 5
  • 52
  • 79
1
if ((new int[]{7,8}).Contains(index))
SQLMason
  • 3,275
  • 1
  • 30
  • 40
  • This answer is wrong. It does not combine multiple conditional expressions, but rather avoids them by calling a completely different method, which may fail to compile or even give a different answer in edge cases. (not sure if different answer is possible with `int[]`, but it is definitely possible in general, if the type other than `int` is used). This is just to say that, starting with an unclear question, one can call any answer wrong! – Rotsor Jun 18 '11 at 02:09
  • 1
    He does not require multiple conditional expressions and never said that in the question. Due to the correct answer selected being very similar to this, I'm afraid that your comment is off. My answer is a solution to the problem as the author intended. Your reason to down vote me for not allowing multiple conditional expressions is in error. Oh well. – SQLMason Jun 18 '11 at 16:37
  • If you read the title of the question you can see that the author asked to *combine multiple conditional expressions*. Also, I don't see where the down-vote assumption came from. – Rotsor Jun 18 '11 at 17:16
  • This entire thread is a disaster. Wrong answers upvoted, correct answers no voted, expensive answers grossly upvoted, and now the author decided to give himself the correct answer... which is wrong because it's bitwise. – SQLMason Jun 21 '11 at 17:08
0

No way to do that, but you could certainly do a range using if( index >=7 && index <= 8 ). But giving it a list of numbers would require you to create an array or list object and then use a method to do this. But that's just overkill.

Adriano Carneiro
  • 57,693
  • 12
  • 90
  • 123
Coeffect
  • 8,772
  • 2
  • 27
  • 42
  • While certainly not as awesome as 48klocs's, I see nothing wrong with the answer. There is no way to do that _without_ creating a list/method. 48kloc's answer is definitely elegant, but performance wise, it's terrible. – Coeffect Jun 17 '11 at 20:15
  • Your answer is to use a range. The question is for an IN clause like SQL. I didn't down vote you, I just don't think it's worth +3 as you didn't answer within the question's scope. Unless you misunderstood the scope... – SQLMason Jun 17 '11 at 20:43
0

Do u need something like that

        int x = 5; 

        if((new int[]{5,6}).Contains(x)) 
        {
            Console.WriteLine("true");


        }
        Console.ReadLine();
AMH
  • 6,363
  • 27
  • 84
  • 135