110

In SQL, you can use the following syntax:

SELECT *
FROM MY_TABLE
WHERE VALUE_1 IN (1, 2, 3)

Is there an equivalent in C#? The IDE seems to recognise "in" as a keyword, but I don't seem to be able to find any information on it.

So, is it possible to do something like the following:

int myValue = 1;
if (myValue in (1, 2, 3))
    // Do something

Instead of

int myValue = 1;
if (myValue == 1 || myValue == 2 || myValue == 3)
    // Do something
abatishchev
  • 98,240
  • 88
  • 296
  • 433
Paul Michaels
  • 16,185
  • 43
  • 146
  • 269
  • I've edited this a little to clarify what I was trying to compare – Paul Michaels Jul 02 '10 at 10:54
  • check another answer added by me – Pranay Rana Jul 02 '10 at 11:05
  • This has already been asked multiple times on stackoverflow... – chiccodoro Jul 02 '10 at 11:18
  • 7
    @chiccodoro if this question has been asked before then flag it as a duplicate and post an answer with the link to the original question, don't just leave a negative comment – Hannish Mar 02 '16 at 08:37
  • I'm still curious why it's not a built in language feature (and, at a minimum, at least for strings). Other languages such as SQL and Python have this feature. Often there is a legitimate reason though and, given the simplicity of this one, I doubt it's never been requested or considered. – BVernon Jun 02 '21 at 19:51
  • 2021 -> C# 9 now allows use of `... is ... or ...` expression. For few options, that can be an easy solution: `if (myValue is 1 or 2 or 3)`. Source: [MS Docs](https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9#pattern-matching-enhancements) – Rick Wolff Jun 24 '21 at 13:56

15 Answers15

150

If you wanted to write .In then you could create an extension that allows you to do that.

static class Extensions
{

    public static bool In<T>(this T item, params T[] items)
    {
        if (items == null)
            throw new ArgumentNullException("items");

        return items.Contains(item);
    }

}


class Program
{

    static void Main()
    {


        int myValue = 1;

        if (myValue.In(1, 2, 3))
            // Do Somthing...

        string ds = "Bob";

        if (ds.In("andy", "joel", "matt")) 
        // Do Someting...
    }
}
Andy Robinson
  • 7,309
  • 2
  • 30
  • 20
87

List.Contains() is I think what you're looking for. C# has in keyword and not an operator which serves completely different purpose then what you're referring in SQL.

There are two ways you can use in keyword in C#. Assume you have a string[] or List in C#.

        string[] names; //assume there are some names;

        //find all names that start with "a"
        var results = from str in names
                      where str.StartsWith("a")
                      select str;

        //iterate through all names in results and print
        foreach (string name in results)
        {
            Console.WriteLine(name);
        }

Referring your edit, I'd put your code this way to do what you need.

        int myValue = 1;
        List<int> checkValues = new List<int> { 1, 2, 3 };

        if (checkValues.Contains(myValue))
            // Do something 
this. __curious_geek
  • 42,787
  • 22
  • 113
  • 137
43

You can do this:

var x = 99; // searched value

if (new[] {1,2,3,99}.Contains(x))
{
   // do something
}
JwJosefy
  • 730
  • 7
  • 12
  • 4
    I preferred this answer to the higher voted ones as the whole point of wanting to do IN instead of repeated equality checks is to reduce code complexity, and this is nice and short and simple! – MrVimes Jul 01 '17 at 22:17
7

There's no "in" operator in C#, the "in" keyword is used only with "foreach (... in ...)" or "from ... in ...".

The LINQ equivalent of your SQL query would be:

List<int> list = new List<int> { 1, 2, 3 };
var query = from row in my_table
            where list.Contains(row.value1)
            select row;
Daniel
  • 15,944
  • 2
  • 54
  • 60
7

You usually use the Contains method of a collection.

myCollection.Where(p => Enumerable.Range(1,3).Contains(p));

I hope it helps.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
luckyluke
  • 1,553
  • 9
  • 16
4

I agree the best way to implement the In operator is with an Extension Method. I did it a little differently:

public static bool In(this string str, string CommaDelimintedStringSet)
{
    string[] Values = CommaDelimintedStringSet.Split(new char[] { ',' });
    foreach (string V in Values)
    {
       if (str == V)
         return true;
    }
    return false;
}

The difference is that you don't have to put quotes around each value, only the entire set of comma delimited values, which is easier to type:

bool result = MyString.In("Val1,Val2,Val3");
Omar
  • 16,329
  • 10
  • 48
  • 66
Chuck Bevitt
  • 57
  • 1
  • 1
  • It would be event better to utilize param-arrays with this function. Like `public static bool In(this string str, params string[] stringSet)` and call it like `bool result = myString.In("Val1", "Val2", "Val3")` – Manuel Hoffmann Oct 04 '16 at 14:13
4

For digits from 0 to 9:

"123".Contains(myValue)

For any other Stuff:

"|1|2|3|".Contains("|" + myValue + "|")
The Hungry Dictator
  • 3,444
  • 5
  • 37
  • 53
  • this will generate problems in some situations, like when `myValue` has `|` characters inside it – sergiol Jan 26 '23 at 17:14
4

Duplicate of : LINQ to SQL in and not in

select * from table where fieldname in ('val1', 'val2') 

or

select * from table where fieldname not in (1, 2) 

The equivalent of IN and NOT IN queries in LINQ to SQL would be something like this:

List<string> validValues = new List<string>() { "val1", "val2"}; 
var qry = from item in dataContext.TableName 
          where validValues.Contains(item.FieldName) 
          select item; 

and this:

List<int> validValues = new List<int>() { 1, 2}; 
var qry = from item in dataContext.TableName 
          where !validValues.Contains(item.FieldName) 
          select item; 
Community
  • 1
  • 1
Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
3

You can write an extension. I wrote one time ago, for making code like

if(someObject.stringPropertyX.Equals("abc") || someObject.stringPropertyX.Equals("def") || ....){
    //do something
    ...
}else{
   //do something other...
   ....
}

more readable with an extention s.t. one was able to write

if(someObject.stringPropertyX.In("abc", "def",...,"xyz"){
   //do something
   ...
}else{
  //do something other...
  ....
}

Here's the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Some.Namespace.Extenders
{
    public static class StringExtender
    {
        /// <summary>
        /// Evaluates whether the String is contained in AT LEAST one of the passed values (i.e. similar to the "in" SQL clause)
        /// </summary>
        /// <param name="thisString"></param>
        /// <param name="values">list of strings used for comparison</param>
        /// <returns><c>true</c> if the string is contained in AT LEAST one of the passed values</returns>
        public static bool In(this String thisString, params string[] values)
        {
            foreach (string val in values)
            {
                if (thisString.Equals(val, StringComparison.InvariantCultureIgnoreCase))
                    return true;
            }

            return false; //no occurence found
        }
    }
}

This is the one specific to my needs at that time, but you may adapt and modify it to match more different types.

Juri
  • 32,424
  • 20
  • 102
  • 136
2

For your updated question, you could also use a switch-statement.

switch (myvalue)
{
   case 1:
   case 2:
   case 3: 
      // your code goes here
  break;
}
Community
  • 1
  • 1
Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
  • 2
    This is what I ended up doing. I suppose the consensus is that there isn't really any facility for this in C#. – Paul Michaels Jul 02 '10 at 11:18
  • 5
    I wouldn't really have accepted this, because it is NOT an answer to the "in" operator question. See the top-voted answer instead... – chiccodoro Jul 02 '10 at 11:21
  • 6
    I would not recommend this approach at all! It's not scalable and has ability to make your fellow programmers' lives miserable! – decyclone Jul 02 '10 at 11:34
  • 3
    @decyclone: Yes, It's all about maintainability. code as if the next programmer to replace you is a serial-killer and knows where you live. – this. __curious_geek Jul 02 '10 at 12:11
  • 1
    I disagree, there was no actual answer to the question (or the answer was "no, that doesn't exist in C#") - so this seemed the closest alternative to me. You also have to bear in mind that the question was based on language functionality and not style. – Paul Michaels Jul 02 '10 at 13:49
2

With C# 9.0 you can write:

if(name is "Anna" or "Mary" or "Sue") { ... }

Unfortunately is is not allowed in expressions (LINQ-methods like .Where() on IQueryable targets).

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Micha
  • 21
  • 2
1

There is no in operator that looks for a value in a collection, instead it's a method of the collection, called Contains.

The most scalable solution is to use a HashSet as the collection. Checking for a value in a HashSet is close to an O(1) operation, compared to doing it in a List where it is an O(n) operation. That means that you can pack a lot of values in a HashSet and it's still fast, while looking for a value in a List gets slower the more values you have.

Example:

var set = new HashSet<int>();
set.Add(1);
set.Add(2);
set.Add(3);

var result = items.Select(i => set.Contains(i.value));
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
1

Common, LINQ way more powerful:

var list = new List<string> { "Tomato", "Orange", "Mango"};
var query = from i in my_table
            from v in list
            where i.Name.StartsWith(v)
            select i;
bjolfr
  • 11
  • 1
0

The in keyword in C# is for the foreach statement and for LINQ query expressions. There is no functionality equivalent to SQL's in operator in C# per se, but LINQ offers similar functionality with Contains().

var list = {1, 2, 3}
var filtered = (
    from item in items
    where list.Contains(item)
    select item).ToArray().
P Daddy
  • 28,912
  • 9
  • 68
  • 92
0

I do something like this:

var shippingAddress = checkoutContext.Addresses.Where(a => (new HashSet<AddressType> { AddressType.SHIPPING_ONLY, AddressType.BILLING_AND_SHIPPING }).Contains(a.AddressType) && a.Id == long.Parse(orderDto.ShippingAddressId)).FirstOrDefault();
BRBdot
  • 758
  • 2
  • 8
  • 20