2009-09-25 3 views
4

Fondamentalement, je donne à l'utilisateur une option pour filtrer un ensemble de fichiers en fonction de leur taille.Comment basculer dynamiquement entre la comparaison des valeurs Inférieur à, Supérieur à ou Egal à?

L'utilisateur sélectionne un type de comparaison (supérieur à, inférieur à, égal à) dans une liste déroulante, puis saisit une taille, en octets, à comparer. Voilà ce que j'ai jusqu'à présent:

switch (cmboCompareType.SelectedText) 
{ 
    case "Greater Than": 
     fileOK = fi[i].Length > int.Parse(txtByteValue.Text); 
     break; 
    case "Less Than": 
     fileOK = fi[i].Length < int.Parse(txtByteValue.Text); 
     break; 
    case "Equal To": 
     fileOK = fi[i].Length == int.Parse(txtByteValue.Text); 
     break; 
} 

Est-il possible de faire ce genre de comparaison plus élégante sans répéter le code tant en C#?

Répondre

10
int value = int.Parse(txtByteValue.Text); 
int len = fi[i].Length; 

switch (cmboCompareType.SelectedText) 
{ 
    case "Greater Than": fileOK = len > value; break; 
    case "Less Than": fileOK = len < value; break; 
    case "Equal To": fileOK = len == value; break; 
} 

TADA! Moins de répétition. ; P

+0

bien cette partie était évidente. Je cherchais plus d'une comparaison "dynamique". –

+0

Eh bien, vous n'avez pas demandé une comparaison dynamique ... vous venez de demander moins de répétitions.J'essayais de faire valoir un point. P – jrista

+0

Eh bien, le titre dit «comment changer DYNAMIQUEMENT ...». Je dois admettre que celui-ci est le plus simpliste, et probablement le plus «élégant» de toutes les réponses à ce jour. –

18

Deux options:

1) Utilisez CompareTo et astro:

int requiredSign; 
switch (cmboCompareType.SelectedText) 
{ 
    case "Greater Than": requiredSign = 1; break; 
    case "Less Than": requiredSign = -1; break; 
    case "Equal To": requiredSign = 0; break; 
    default: throw new ArgumentException(); 
} 
fileOK = Math.Sign(fi[i].Length.Compare(txtByteValue.Text)) == requiredSign; 

2) Utilisez un délégué:

static readonly Func<int, int, bool> GreaterThan = (x, y) => x > y; 
static readonly Func<int, int, bool> LessThan = (x, y) => x < y; 
static readonly Func<int, int, bool> Equal = (x, y) => x == y; 
... 

Func<int, int, bool> comparison; 
switch (cmboCompareType.SelectedText) 
{ 
    case "Greater Than": comparison = GreaterThan; break; 
    case "Less Than": comparison = LessThan; break; 
    case "Equal To": comparison = Equal; break; 
    default: throw new ArgumentException(); 
} 
fileOK = comparison(fi[i].Length, int.Parse(txtByteValue.Text)); 
+0

+1 pour l'option de délégué. Résout le problème DRY avec le code original sans sacrifier la lisibilité. – JohnFx

+0

+1: la sélection dynamique des délégués, plutôt que des valeurs particulières, est un motif de conception sous-estimé. C'est aussi plus extensible que l'approche Math.Sign: si l'OP ajoute plus d'éléments à sa liste déroulante, il peut très facilement modifier le code pour récupérer le comparateur approprié à partir de Dictionary >. – Juliet

+0

J'aime mieux l'option 2. –

1
int actual = Math.Sign(fi[i].Length.CompareTo(int.Parse(txtByteValue.Text))); 
int expected; 

switch (cmboCompareType.SelectedText) 
{ 
    case "Greater Than": expected = +1; break; 
    case "Less Than": expected = -1; break; 
    case "Equal To":  expected = 0; break; 
} 

fileOK = (actual == expected); 
1

Si vous avez une carte, vous peut utiliser quelque chose comme:

private int CompareOp(string Text) 
{ 
    switch (cmboCompareType.SelectedText) 
    { 
     case "Greater Than": 
      return 1; 
     case "Less Than": 
      return -1; 
     case "Equal To": 
      return 0; 
    } 
} 

// In your method: 
fileOK = (fi[i].Length.CompareTo(value) == CompareOp(cmboCompareType.SelectedText); 
1

Créer une méthode d'extension sur int

public static int Compare(this int a, int b, string compareType) 
{ 
    switch (CompareType) 
    { 
     case "Greater Than": 
      return fi[i].Length > int.Parse(txtByteValue.Text); 
      break; 
     case "Less Than": 
      return fi[i].Length < int.Parse(txtByteValue.Text); 
      break; 
     case "Equal To": 
      return fi[i].Length == int.Parse(txtByteValue.Text); 
      break; 
    } 
} 

puis l'utiliser comme:

fileOK = fi[i].Length.Compare(int.Parse(txtByteValue.Text), cmboCompareType.SelectedTex); 
+0

N'adresse pas le problème "Ne vous répétez pas" –

+0

@Nathan: cela dépend de la fréquence d'utilisation. la méthode d'extension apparaîtra sur tous les int si cette comparaison est effectuée dans de nombreux endroits différents, alors la méthode Compare est implémentée une seule fois et utilisée partout. –

1

Vous pouvez également ajouter les valeurs -1, 0, 1 à la propriété de la valeur de chaque élément de zone de liste déroulante et puis le code ressemblerait à:

fileOK = fi[i].Length.CompareTo(int.Parse(txtByteValue.Text) == cmboCompareType.SelectedValue; 
+0

Ya c'est le processus de réflexion qui m'a conduit à la réponse que je viens d'ajouter. Mais au lieu d'ajouter des valeurs, je viens de compenser l'index par un. –

0

Ma propre idée, inspirée par les solutions qui ont utilisé Math.Sign(). Puisque la boîte déroulante a trois valeurs, qui auront un indice de 0,1, et 2, je pourrais soustraire 1 pour obtenir -1,0,1, puis utiliser cela pour comparer avec le signe, en tant que tel:

int sign = Math.Sign(fi[i].Length.CompareTo(int.Parse(txtByteValue.Text))); 
fileOK = sign == (cmboCompareType.SelectedIndex - 1); 

cela dépendra des éléments dans la zone de liste étant mis dans cet ordre précis:
Moins de
égal à
supérieur à

Et bien sûr, ne fonctionnerait que si ce sont les seules valeurs qui sera jamais dans la liste. Probablement pas la meilleure solution, mais j'ai eu un coup de pied du fait que j'ai accompli ceci dans seulement deux lignes de code.

EDIT: techincally je pouvais simplifier cela à une seule ligne de code:

fileOk=(cmboCompareType.SelectedIndex-1) == Math.Sign(fi[i].Length.CompareTo(int.Parse(txtByteValue.Text))); 
5

Je ne suis pas fan de déclarations de cas, la même chose que, juste une autre façon.


var fileOK = new Dictionary<string, Func<int, int, bool>> 
    (StringComparer.OrdinalIgnoreCase) 
    { 
     { "Greater Than", (x, y) => x > y }, 
     { "Less Than", (x, y) => x < y }, 
     { "Equal To", (x, y) => x == y } 
    }[cmboCompareType.SelectedText](fi.Length, int.Parse(txtByteValue.Text)); 
+0

très intéressant –

Questions connexes