2010-10-04 13 views
37

Y a-t-il un moyen de créer une condition de cas dans une instruction switch où vous dites si une chaîne commence par quelque chose?C# Chaîne de casse à partir de

ex

Switch (mystring) 
{ 
    case("abc")://String begins with abc (abcd or abc1 or abcz or abc.. or abc will fall in this condition). 
     //Do Something 
     break; 
    default: 
     break; 
} 

MISE À JOUR D'autres chaînes peuvent être différentes longueurs.

abc ..

abczyv

DCS2.

azerty

comme ... k

+0

sont vos cas de commutation tout va être la même longueur? par exemple. ABC, XYZ – Paddy

+0

@Paddy: Non, ils peuvent être de longueur différente.Merci. – Amra

Répondre

28

Si vous saviez que la durée des conditions dans lesquelles vous se soucierait seraient tous de la même longueur, vous pouvez:

switch(mystring.substring(0, Math.Min(3, mystring.Length)) 
{ 
    case "abc": 
    //do something 
    break; 
    case "xyz": 
    //do something else 
    break; 
    default: 
    //do a different thing 
    break; 
} 

Le Math.Min(3, mystring.Length) est là pour qu'une chaîne de moins de 3 caractères ne jeter une exception sur l'opération de sous-chaîne.

Il existe des extensions de cette technique pour correspondre, par ex. un tas de chaînes à 2 caractères et un tas de chaînes à 3 caractères, où certaines comparaisons à 2 caractères sont suivies de comparaisons à 3 caractères. Cependant, à moins d'avoir un très grand nombre de chaînes de ce type, il devient rapidement moins efficace que le chaînage if-else simple pour le code courant et la personne qui doit le maintenir.

Modifier: Ajouté depuis que vous avez maintenant déclaré qu'ils seront de différentes longueurs. Vous pourriez faire le modèle que j'ai mentionné de vérifier les premiers caractères X et ensuite les caractères Y suivants et ainsi de suite, mais à moins qu'il y ait un motif où la plupart des cordes sont de la même longueur, cela sera à la fois inefficace et horrible. de pessimisation prématurée). Le motif de commande est mentionné dans une autre réponse, donc je ne donnerai pas de détails à ce sujet, comme c'est le cas lorsque vous mappez des motifs de chaîne à des ID, mais ils sont en option. Je ne changerais pas de chaînes if-else pour commander ou mapper des modèles pour gagner l'efficacité parfois a sur if-else, comme vous perdez plus dans les comparaisons pour la commande ou l'obtention du modèle ID. Je ferais bien de le faire si cela rendait le code plus clair.

Une chaîne d'if-else peut très bien fonctionner, soit avec des comparaisons de chaînes, soit avec des expressions régulières (cette dernière si vous avez des comparaisons plus compliquées que les préfixes-match, ce qui serait probablement plus simple et plus rapide je mentionne reg-ex juste parce qu'ils fonctionnent parfois bien avec des cas plus généraux de ce type de pattern).Si vous optez pour if-elses, essayez de savoir quels cas vont se produire le plus souvent, et faites ces tests avant ceux pour les cas moins fréquents (bien sûr, si "commence par abcd" est un cas à chercher, il faudrait vérifier avant "commence par abc").

+1

'Math.Min (3, mystring.Length)' belle touche, ne savait pas de cela +1 –

5

Si tous les cas ont la même longueur que vous pouvez utiliser
switch (mystring.SubString(0,Math.Min(len, mystring.Length))).
Une autre option consiste à avoir une fonction qui retournera categoryId en fonction de la chaîne et activera l'ID.

1

En plus de la réponse de sous-chaîne, vous pouvez le faire sous le nom mystring.SubString (0,3) et vérifier dans l'instruction case si elle est "abc". Mais avant l'instruction switch, vous devez vous assurer que votre mystring a au moins 3 de longueur.

13

Réponse courte: Non

L'instruction switch prend une expression qui est évaluée uniquement une fois. Basé sur le résultat, un autre morceau de code est exécuté.

Alors quoi? => String.StartsWith est une fonction. Avec un paramètre donné, c'est une expression. Cependant, pour votre cas, vous devez passer un paramètre différent pour chaque cas, de sorte qu'il ne peut pas être évalué qu'une seule fois.

La réponse longue # 1 a été donnée par d'autres personnes.

Réponse longue # 2:

Selon ce que vous essayez d'atteindre, vous pourriez être intéressé par le Command Pattern/Chain-of-responsibility pattern. Appliqué à votre cas, chaque morceau de code serait représenté par une implémentation d'une commande . En plus de la méthode execute, la commande peut fournir une méthode booléenne Accepter, qui vérifie si la chaîne donnée commence par le paramètre correspondant. Avantage: À la place de votre déclaration de commutateur codée en dur, de vos évaluations StartsWith codées en dur et de vos chaînes codées en dur, vous disposez de beaucoup plus de flexibilité.

L'exemple que vous avez donné à votre question doit ressembler à ceci:

var commandList = new List<Command>() { new MyABCCommand() }; 

foreach (Command c in commandList) 
{ 
    if (c.Accept(mystring)) 
    { 
     c.Execute(mystring); 
     break; 
    } 
} 

class MyABCCommand : Command 
{ 
    override bool Accept(string mystring) 
    { 
     return mystring.StartsWith("abc"); 
    } 
}  
3

Si le domaine du problème a une sorte de concept d'en-tête de chaîne, cela pourrait être modélisé comme ENUM.

switch(GetStringHeader(s)) 
{ 
    case StringHeader.ABC: ... 
    case StringHeader.QWERTY: ... 
    ... 
} 

StringHeader GetStringHeader(string s) 
{ 
    if (s.StartsWith("ABC")) return StringHeader.ABC; 
    ... 
} 

enum StringHeader { ABC, QWERTY, ... } 
-7

Essayez et dire à mon si cela fonctionne espère que cela vous aider:

string value = Convert.ToString(Console.ReadLine()); 

Switch(value) 
{ 
    Case "abc": 

    break; 

    default: 

    break; 
}  
+0

pourquoi j'étais downvoted ??? –

+4

Votre réponse ne fonctionnera pas, une déclaration de cas C# de base est ce que vous avez montré. Cela correspond à la chaîne entière, pas à la portion de départ (que la question demande). – wonea

Questions connexes