Existe-t-il un opérateur C # IN?

89

En SQL, vous pouvez utiliser la syntaxe suivante:

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

Existe-t-il un équivalent en C #? L'IDE semble reconnaître "in" comme un mot-clé, mais je ne semble pas pouvoir trouver d'informations à ce sujet.

Alors, est-il possible de faire quelque chose comme ce qui suit:

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

Au lieu de

int myValue = 1;
if (myValue == 1 || myValue == 2 || myValue == 3)
    // Do something
Paul Michaels
la source
J'ai édité ceci un peu pour clarifier ce que j'essayais de comparer
Paul Michaels
vérifier une autre réponse ajoutée par moi
Pranay Rana
Cela a déjà été demandé plusieurs fois sur stackoverflow ...
chiccodoro
3
@chiccodoro si cette question a déjà été posée, marquez-la comme un doublon et publiez une réponse avec le lien vers la question d'origine, ne laissez pas simplement un commentaire négatif
Hannish

Réponses:

125

Si vous voulez écrire .In, vous pouvez créer une extension qui vous permet de le faire.

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
la source
1
N'oubliez pas d'ajouter en utilisant System.Linq;
Tanner Ornelas
In est tellement mieux à lire que contient ... Plus facile à comprendre
Konrad
84

List.Contains()est je pense ce que vous cherchez. C # a in keywordet non pas un operatorobjectif complètement différent de celui auquel vous faites référence en SQL.

Il existe deux façons d'utiliser le inmot clé en C #. Supposons que vous ayez une chaîne [] ou une liste en 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);
        }

En me référant à votre modification, je mettrais votre code de cette façon pour faire ce dont vous avez besoin.

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

        if (checkValues.Contains(myValue))
            // Do something 
ce. __curious_geek
la source
4
Les gens voient SQL et passent instantanément à LINQ, mais cette fonction simple est probablement exactement ce qu'il veut
Bart van Heukelom
29

Tu peux le faire:

var x = 99; // searched value

if (new[] {1,2,3,99}.Contains(x))
{
   // do something
}
JwJosefy
la source
2
J'ai préféré cette réponse aux réponses les plus votées car le but de vouloir faire IN au lieu de contrôles d'égalité répétés est de réduire la complexité du code, et c'est gentil et court et simple!
MrVimes
1
Merci @MrVimes!
JwJosefy
7

Vous utilisez généralement la Containsméthode d'une collection.

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

J'espère que cela aide.

Lucky Luke
la source
6

Il n'y a pas d'opérateur "in" en C #, le mot clé "in" est utilisé uniquement avec "foreach (... in ...)" ou "from ... in ...".

L'équivalent LINQ de votre requête SQL serait:

List<int> list = new List<int> { 1, 2, 3 };
var query = from row in my_table
            where list.Contains(row.value1)
            select row;
Daniel
la source
4

Duplicata de: LINQ to SQL dans et pas dans

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

ou

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

L'équivalent des requêtes IN et NOT IN dans LINQ to SQL serait quelque chose comme ceci:

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

et ça:

List<int> validValues = new List<int>() { 1, 2}; 
var qry = from item in dataContext.TableName 
          where !validValues.Contains(item.FieldName) 
          select item; 
Pranay Rana
la source
Oui - désolé, j'ai édité ma question, car ce que je demande ne concerne pas linq
Paul Michaels
4

Je suis d'accord que la meilleure façon d'implémenter l'opérateur In est d'utiliser une méthode d'extension. Je l'ai fait un peu différemment:

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;
}

La différence est que vous n'avez pas à mettre de guillemets autour de chaque valeur, uniquement l'ensemble complet de valeurs délimitées par des virgules, ce qui est plus facile à taper:

bool result = MyString.In("Val1,Val2,Val3");
Chuck Bevitt
la source
Il serait préférable d'utiliser des tableaux de paramètres avec cette fonction. Aimez public static bool In(this string str, params string[] stringSet)et appelez-le commebool result = myString.In("Val1", "Val2", "Val3")
Manuel Hoffmann
2

Vous pouvez écrire une extension. J'ai écrit il y a une fois, pour créer du code comme

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

plus lisible avec une extension on a pu écrire

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

Voici le 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
        }
    }
}

C'est celui qui correspond à mes besoins à ce moment-là, mais vous pouvez l'adapter et le modifier pour qu'il corresponde à d'autres types.

Juri
la source
2

Pour les chiffres de 0 à 9:

"123".Contains(myValue)

Pour toute autre chose:

"|1|2|3|".Contains("|" + myValue + "|")
user3354025
la source
2

Pour votre question mise à jour, vous pouvez également utiliser une instruction switch.

switch (myvalue)
{
   case 1:
   case 2:
   case 3: 
      // your code goes here
  break;
}
Pranay Rana
la source
1
C'est ce que j'ai fini par faire. Je suppose que le consensus est qu'il n'y a pas vraiment de facilité pour cela en C #.
Paul Michaels
5
Je n'aurais pas vraiment accepté cela, car ce n'est PAS une réponse à la question de l'opérateur «in». Voir plutôt la réponse la plus votée ...
chiccodoro
6
Je ne recommanderais pas du tout cette approche! Il n'est pas évolutif et a la capacité de rendre la vie de vos collègues programmeurs misérable!
décyclone le
3
@decyclone: ​​Oui, tout est question de maintenabilité. code comme si le prochain programmeur à vous remplacer est un tueur en série et sait où vous habitez.
ça. __curious_geek
Je ne suis pas d'accord, il n'y avait pas de réponse réelle à la question (ou la réponse était "non, cela n'existe pas en C #") - donc cela me semblait l'alternative la plus proche. Vous devez également garder à l'esprit que la question était basée sur la fonctionnalité du langage et non sur le style.
Paul Michaels
1

Il n'y a pas d'opérateur in qui recherche une valeur dans une collection, c'est plutôt une méthode de la collection, appelée Contains.

La solution la plus évolutive consiste à utiliser a HashSetcomme collection. Vérifier une valeur dans a HashSetest proche d'une opération O (1), par rapport à le faire dans a Listoù il s'agit d'une opération O (n). Cela signifie que vous pouvez regrouper beaucoup de valeurs dans a HashSetet que c'est toujours rapide, tandis que la recherche d'une valeur dans a Listdevient plus lente plus vous avez de valeurs.

Exemple:

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

var result = items.Select(i => set.Contains(i.value));
Guffa
la source
1

Commun, LINQ bien plus puissant:

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
la source
0

Le inmot clé en C # est pour l' foreachinstruction et pour les expressions de requête LINQ. Il n'y a pas de fonctionnalité équivalente à l' inopérateur SQL en C # en soi, mais LINQ offre des fonctionnalités similaires avec Contains().

var list = {1, 2, 3}
var filtered = (
    from item in items
    where list.Contains(item)
    select item).ToArray().
Papa
la source
0

Je fais quelque chose comme ça:

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
la source