Esiste un operatore C # IN?


89

In SQL è possibile utilizzare la seguente sintassi:

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

C'è un equivalente in C #? L'IDE sembra riconoscere "in" come parola chiave, ma non mi sembra di essere in grado di trovare alcuna informazione su di esso.

Quindi, è possibile fare qualcosa come il seguente:

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

Invece di

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

L'ho modificato un po 'per chiarire cosa stavo cercando di confrontare
Paul Michaels

controlla un'altra risposta aggiunta da me
Pranay Rana

Questo è già stato chiesto più volte su
stackoverflow

3
@chiccodoro se questa domanda è stata posta prima, contrassegnala come duplicata e pubblica una risposta con il link alla domanda originale, non lasciare un commento negativo
Hannish

Risposte:


125

Se volessi scrivere .In allora potresti creare un'estensione che ti permetta di farlo.

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
Ricorda solo di aggiungere usando System.Linq;
Tanner Ornelas

In è molto meglio leggere che contiene ... Più facile da capire
Konrad

84

List.Contains()penso sia quello che stai cercando. C # ha in keyworde non ha uno operatorscopo completamente diverso da quello a cui ti riferisci in SQL.

Esistono due modi per utilizzare la inparola chiave in C #. Supponiamo di avere una stringa [] o un elenco 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);
        }

Facendo riferimento alla tua modifica, metterei il tuo codice in questo modo per fare ciò di cui hai bisogno.

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

        if (checkValues.Contains(myValue))
            // Do something 

4
Le persone vedono SQL e passano immediatamente a LINQ, ma questa semplice funzione è probabilmente esattamente ciò che vuole
Bart van Heukelom

29

Puoi farlo:

var x = 99; // searched value

if (new[] {1,2,3,99}.Contains(x))
{
   // do something
}

2
Ho preferito questa risposta a quelle con il voto più alto perché il punto centrale di voler fare IN invece di ripetuti controlli di uguaglianza è ridurre la complessità del codice, e questo è carino, breve e semplice!
MrVimes

1
Grazie @MrVimes!
JwJosefy

7

Di solito usi il Containsmetodo di una raccolta.

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

Spero possa essere d'aiuto.


6

Non esiste un operatore "in" in C #, la parola chiave "in" viene utilizzata solo con "foreach (... in ...)" o "from ... in ...".

L'equivalente LINQ della tua query SQL sarebbe:

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

4

Duplicato di: LINQ to SQL in e non in

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

o

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

L'equivalente delle query IN e NOT IN in LINQ to SQL sarebbe qualcosa del genere:

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

e questo:

List<int> validValues = new List<int>() { 1, 2}; 
var qry = from item in dataContext.TableName 
          where !validValues.Contains(item.FieldName) 
          select item; 

Sì, scusa, ho modificato la mia domanda, poiché ciò che sto chiedendo non si riferisce a linq
Paul Michaels

4

Sono d'accordo che il modo migliore per implementare l'operatore In è con un metodo di estensione. L'ho fatto in modo leggermente diverso:

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 differenza è che non è necessario inserire virgolette attorno a ciascun valore, solo l'intero set di valori delimitati da virgole, che è più facile da digitare:

bool result = MyString.In("Val1,Val2,Val3");

Sarebbe meglio utilizzare param-array con questa funzione. Mi piace public static bool In(this string str, params string[] stringSet)e chiamalo similebool result = myString.In("Val1", "Val2", "Val3")
Manuel Hoffmann il

2

Puoi scrivere un'estensione. Ho scritto una volta fa, per creare codice simile

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

più leggibile con un'estensione st si era in grado di scrivere

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

Ecco il codice :

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

Questo è quello specifico per le mie esigenze in quel momento, ma puoi adattarlo e modificarlo per adattarlo a più tipi diversi.


2

Per cifre da 0 a 9:

"123".Contains(myValue)

Per qualsiasi altra cosa:

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

2

Per la tua domanda aggiornata, potresti anche utilizzare un'istruzione switch.

switch (myvalue)
{
   case 1:
   case 2:
   case 3: 
      // your code goes here
  break;
}

1
Questo è quello che ho finito per fare. Suppongo che il consenso sia che non esiste davvero alcuna funzionalità per questo in C #.
Paul Michaels

5
Non l'avrei davvero accettato, perché NON è una risposta alla domanda dell'operatore "in". Guarda la risposta più votata invece ...
chiccodoro

6
Non consiglierei affatto questo approccio! Non è scalabile e ha la capacità di rendere miserabili le vite dei tuoi colleghi programmatori!
deciclone

3
@decyclone: ​​Sì, è tutta una questione di manutenibilità. codice come se il prossimo programmatore a rimpiazzarti fosse un serial killer e sapesse dove vivi.
questo. __curious_geek

Non sono d'accordo, non c'era una risposta reale alla domanda (o la risposta era "no, non esiste in C #") - quindi questa mi è sembrata l'alternativa più vicina. Devi anche tenere presente che la domanda era basata sulla funzionalità del linguaggio e non sullo stile.
Paul Michaels

1

Non esiste un operatore in che cerchi un valore in una raccolta, invece è un metodo della raccolta, chiamato Contains.

La soluzione più scalabile è usare a HashSetcome raccolta. Il controllo di un valore in a HashSetè vicino a un'operazione O (1), rispetto a farlo in a Listdove è un'operazione O (n). Ciò significa che puoi impacchettare molti valori in a HashSeted è ancora veloce, mentre la ricerca di un valore in a Listdiventa più lenta più valori hai.

Esempio:

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

var result = items.Select(i => set.Contains(i.value));

1

Comune, LINQ molto più potente:

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

La inparola chiave in C # è per l' foreachistruzione e per le espressioni di query LINQ. Non esiste una funzionalità equivalente all'operatore SQL inin C # di per sé, ma LINQ offre funzionalità simili con Contains().

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

0

Faccio qualcosa del genere:

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();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.