2009-08-27 7 views
1

Je veux tester si une certaine chaîne est contenue dans une courte liste de chaînes. Actuellement le code est comme ceci:Existe-t-il un meilleur moyen d'écrire une nouvelle liste <string> {"a", "b"}. Contient (str)?

if (new List<string> { "A", "B", "C" }.Contains (str)) { 

Cependant, ceci semble gonflé. Par exemple, iirc, en Java je pourrais simplement écrire {"A", "B", "C"}.Contains(str) ce qui serait préférable à ce qui précède.

Je suis sûr qu'il y a un meilleur moyen en C#. Pourriez-vous le signaler?

Répondre

6

Vous pouvez écrire une méthode d'extension:

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

public static bool In<T>(this T obj, IEnumerable<T> candidates) 
{ 
    if(obj == null) throw new ArgumentNullException("obj"); 
    return (candidates ?? Enumerable.Empty<T>()).Contains(obj); 
} 

que vous pourriez ensuite utiliser pour faire:

if(str.In("A", "B", "C")) { ... } 
+0

Une approche intéressante. En ce moment, j'aime mieux la deuxième solution de Fredrik, mais je garderai votre idée à l'esprit.+1 – mafu

+0

Décidé d'accepter cette réponse de toute façon, car il est plus universel. – mafu

6

Je suppose que vous pouvez raccourcir jusqu'à:

if ((new []{ "A", "B", "C" }).Contains (str)) { 

Je ne sais pas combien d'une différence réelle il serait bien.

Mise à jour: si vous savez que vous allez tester exactement une lettre, je ne vois aucune raison de faire une liste ou un tableau de celui-ci:

if ("ABC".Contains(str)) { 

Ce code est à la fois plus court et plus rapide. Mais là encore, je suppose que les chaînes d'une seule lettre étaient simplement des échantillons ...

+0

qui est déjà une grosse amélioration. Je suppose que c'est un peu plus rapide aussi. – mafu

+0

@mafutrct: J'ai fait un test de performance et il me semble que ma solution est plus lente. Donc maintenant c'est un choix entre un code plus court ou plus rapide; o) –

+0

Heureusement, en ce moment, j'ai vraiment besoin de tester des caractères uniques seulement. Comment pourrais-je manquer "ABC" .Contains ?! – mafu

2

Qu'en est cette approche:

"A;B;C".Split(';').Contains(str); 
+0

C'est un peu plus court, mais aussi moins facile à lire et la performance est probablement pire. – mafu

+0

s/probablement/certainement/- ne pas coller cela dans une boucle ... – ijw

+0

Bien sûr, la performance est pire. Si cela compte dans le cas de l'op, c'est une autre question :) – Christian

2

Si votre courte liste de chaînes sont constantes, vous devez utiliser un tableau de chaînes static readonly . L'avantage est qu'il est facile d'écrire et n'instancie pas la nouvelle liste chaque fois que vous devez effectuer la vérification.

private static readonly string[] Names = new string[] { "A", "B", "C" }; 

... 

if (Names.Contains(str)) { 

Toutefois, cette solution n'est pas évolutive car la recherche est effectuée de manière linéaire. Vous pouvez également définir votre tableau de constantes de manière triée et utiliser BinarySearch sur le tableau.

// this has to be sorted 
private static readonly string[] Names = new string[] { "A", "B", "C" }; 

... 

if (Array.BinarySearch(Names, str) >= 0) { 
+0

D'un point de vue performance, j'aime votre solution. Cependant, ma principale préoccupation était la longueur du code. – mafu

2

Pour changer complètement en place:

switch(str){ 
    case "A": 
    case "B": 
    case "C": 
     contains = true; 
     break; 

    default: 
     contains = false; 
     break; 
} 
+0

Trop de code :) – mafu

+0

Juste offrant une alternative :) –