web-dev-qa-db-fra.com

si les déclarations correspondant à plusieurs valeurs

Un moyen plus facile d'écrire cette déclaration if?

if (value==1 || value==2)

Par exemple ... en SQL, vous pouvez dire where value in (1,2) au lieu de where value=1 or value=2.

Je cherche quelque chose qui fonctionnerait avec n'importe quel type de base ... string, int, etc.

68
Ricky

Que diriez-vous:

if (new[] {1, 2}.Contains(value))

C'est un bidouillage cependant :)

Ou si cela ne vous dérange pas de créer votre propre méthode d'extension, vous pouvez créer:

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

Et vous pouvez l'utiliser comme ceci:

if (1.In(1, 2))

:)

115
Amry

Une manière plus compliquée :) qui émule le 'IN' de SQL:

public static class Ext {    
    public static bool In<T>(this T t,params T[] values){
        foreach (T value in values) {
            if (t.Equals(value)) {
                return true;
            }
        }
        return false;
    }
}

if (value.In(1,2)) {
    // ...
}

Mais optez pour la méthode standard, elle est plus lisible.

EDIT: une meilleure solution, selon la suggestion de @ Kobi:

public static class Ext {    
    public static bool In<T>(this T t,params T[] values){
        return values.Contains(t);
    }
}
35
Paolo Tedesco

Est-ce ce que vous recherchez ?

if (new int[] { 1, 2, 3, 4, 5 }.Contains(value))
24
Homam

Sinon, et cela vous donnerait plus de flexibilité si le test de valeurs autres que 1 ou 2 à l'avenir, consiste à utiliser une instruction switch

switch(value)
{
case 1:
case 2:
   return true;
default:
   return false
}
6
jules

Si vous avez une liste, vous pouvez utiliser .Contains (votreObjet), si vous ne le cherchez que si il existe (comme un où). Sinon, regardez la méthode d'extension Linq .Any ().

6
Nik

En utilisant Linq,

if(new int[] {1, 2}.Contains(value))

Mais je devrais penser que votre original si est plus rapide.

5
Joel Rondeau

Si vous recherchez plusieurs fois une valeur dans une liste fixe de valeurs dans une longue liste, utilisez HashSet <T>. Si la liste est très courte (<~ 20 éléments), les performances de List en fonction de ce test pourraient être meilleures { performances de HashSet vs. List }

HashSet<int> nums = new HashSet<int> { 1, 2, 3, 4, 5 };
// ....
if (nums.Contains(value))
5
detale

Généralement non.

Oui, il y a des cas où la liste est dans une Array ou List, mais ce n'est pas le cas général.

3
Steven Sudit

Utilisation de méthodes d'extension:

public static class ObjectExtension
{
    public static bool In(this object obj, params object[] objects)
    {
        if (objects == null || obj == null)
            return false;
        object found = objects.FirstOrDefault(o => o.GetType().Equals(obj.GetType()) && o.Equals(obj));
        return (found != null);
    }
}

Maintenant vous pouvez faire ceci:

string role= "Admin";
if (role.In("Admin", "Director"))
{ 
    ...
} 
1
goenning

Plus facile est subjectif, mais peut-être que la déclaration de commutateur serait plus facile? Il n'est pas nécessaire de répéter la variable, de sorte qu'un plus grand nombre de valeurs peuvent tenir sur la ligne et une ligne avec de nombreuses comparaisons est plus lisible que la contrepartie utilisant l'instruction if.

1
Tim

Une méthode d'extension comme celle-ci le ferait ...

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

Utilisez-le comme ceci:

Console.WriteLine(1.In(1,2,3));
Console.WriteLine("a".In("a", "b"));
1
Allrameest

Dans vb.net ou C #, je m'attendrais à ce que l'approche générale la plus rapide pour comparer une variable à un nombre raisonnable d'objets nommés séparément (par opposition à, par exemple, tous les éléments d'une collection) consiste à simplement comparer chaque objet avec le comparateur comme tu l'as fait. Il est certainement possible de créer une instance d'une collection et de voir si elle contient l'objet. Cela peut être plus expressif que de comparer l'objet à tous les éléments individuellement, mais à moins d'utiliser une construction que le compilateur peut reconnaître explicitement, ce code sera certainement beaucoup plus lent que la simple comparaison individuelle. Je ne voudrais pas m'inquiéter de la vitesse si le code, par nature, s'exécutait au plus quelques centaines de fois par seconde, mais je me méfierais du fait que le code soit réutilisé pour quelque chose qui est exécuté beaucoup plus souvent que prévu.

Une autre approche, si une variable ressemble à un type d’énumération, consiste à choisir des valeurs d’énumération puissantes pour permettre l’utilisation de masques de bits. Si le type d’énumération a 32 valeurs valides ou moins (par exemple, en commençant Harry = 1, Ron = 2, Hermione = 4, Ginny = 8, Neville = 16), on peut les stocker dans un entier et rechercher plusieurs bits à la fois dans un seul operation ((if ((thisOne & (Harry | Ron | Neville | Beatrix))!! = 0)/* Faites quelque chose * /. Ceci autorisera un code rapide, mais se limitera à des énumérations avec un petit nombre de valeurs.

Une approche un peu plus puissante, mais qui doit être utilisée avec précaution, consiste à utiliser certains bits de la valeur pour indiquer les attributs de quelque chose, tandis que d'autres bits identifient l'élément. Par exemple, le bit 30 pourrait indiquer qu’un personnage est un homme, le bit 29 pourrait indiquer un ami de Harry, etc., tandis que les bits inférieurs distinguent les caractères. Cette approche permettrait d’ajouter des personnages qui peuvent être ou non amis de Harry, sans exiger que le code vérifiant le changement d’ami de Harry soit modifié. Cela pose un inconvénient, à savoir qu'il faut distinguer les constantes d'énumération utilisées pour définir une valeur d'énumération de celles utilisées pour la tester. Par exemple, pour définir une variable afin qu'elle indique Harry, vous pouvez définir la valeur sur 0x60000001, mais pour voir si une variable IS Harry, vous devez la tester à l'aide de 0x00000001.

Une autre approche, qui peut être utile si le nombre total de valeurs possibles est modérée (par exemple entre 16 et 16 000 environ) consiste à associer un tableau d’indicateurs à chaque valeur. On pourrait alors coder quelque chose du type "if (((characterAttributes [theCharacter] & aleigh & character.ttribute.Male))!! = 0)". Cette approche fonctionnera mieux lorsque le nombre de caractères est assez petit. Si array est trop grand, les erreurs de cache peuvent ralentir le code au point que tester sur un petit nombre de caractères individuellement serait plus rapide.

1
supercat
public static bool EqualsAny<T>(IEquatable<T> value, params T[] possibleMatches) {
    foreach (T t in possibleMatches) {
        if (value.Equals(t))
            return true;
    }
    return false;
}
public static bool EqualsAny<T>(IEquatable<T> value, IEnumerable<T> possibleMatches) {
    foreach (T t in possibleMatches) {
        if (value.Equals(t))
            return true;
    }
    return false;
}
0
JWL_

J'avais le même problème mais je l'ai résolu avec une instruction switch Switch (une valeur que vous allumez) { Cas 1: le code que vous voulez arriver; cas 2: le code que vous voulez voir apparaître; default: renvoyer une valeur }

0
Ernest Mushinge