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

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

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 

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
}

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.


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;

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; 

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");

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.


2

Pour les chiffres de 0 à 9:

"123".Contains(myValue)

Pour toute autre chose:

"|1|2|3|".Contains("|" + myValue + "|")

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

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

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;

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().

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();
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.