Comment puis-je faire cela avec élégance avec C # et .NET 3.5 / 4?
Par exemple, un nombre peut être compris entre 1 et 100.
Je sais qu'un simple si suffirait; mais le mot clé de cette question est l'élégance. C'est pour mon projet de jouet pas pour la production.
Ces questions ne concernaient pas la vitesse, mais la beauté du code. Arrêtez de parler d'efficacité et autres; souvenez-vous que vous prêchez à la chorale.
if
n'est pas "baroque", ne le répare pas.Réponses:
Il existe de nombreuses options:
Consultez également cet article SO pour les options de regex.
la source
if
déclaration. Cela accomplit certainement cela ...;)Tu veux dire?
ou
la source
Juste pour ajouter au bruit ici, vous pouvez créer une méthode d'extension:
Ce qui vous permettrait de faire quelque chose comme ...
Cela étant dit, cela semble être une chose idiote à faire lorsque le chèque lui-même n'est qu'une ligne.
la source
Comme d'autres l'ont dit, utilisez un simple if.
Vous devriez penser à la commande.
par exemple
est plus facile à lire que
la source
1 <= x <= 100
.=
au lieu de==
. Cela n'aide pas avec les opérateurs relationnels de non-égalité - mais il est facile de s'habituer à l'utiliser de manière cohérente.x
un appel de fonction complexe ou une expression Linq qui prend du temps. Dans ce cas, vous feriez cela deux fois, ce qui n'est pas une bonne chose. Bien sûr, vous devriez stocker la valeur dans une variable locale temporaire, mais il existe certains cas (par exemple dans les instructions else-if) où vous ne voulez appeler les fonctions qu'après l'échec des autres if ou else-if. Avec les variables temporaires, vous devez de toute façon les appeler avant. Une méthode d'extension (mentionnée dans d'autres réponses) est la meilleure solution à mon humble avis dans ces cas.Dans le code de production, j'écrirais simplement
C'est facile à comprendre et très lisible.
Voici une méthode intelligente qui réduit le nombre de comparaisons de deux à un en utilisant des mathématiques. L'idée est que l'un des deux facteurs devient négatif si le nombre se situe en dehors de la plage et zéro si le nombre est égal à l'une des bornes:
Si les limites sont inclusives:
ou
Si les limites sont exclusives:
ou
la source
1 < x && x < 100
code productif. C'est plus facile à comprendre.1 < x & x < 100
(no && short circuit) indique au compilateur qu'il peut toujours évaluerx < 100
quel que soit le résultat de1 < x
. Curieusement (en raison de la prédiction de branche), il est plus rapide de toujours faire cette opération simple que de l'ignorer parfois.Je propose ceci:
Exemples:
et bien sûr avec des variables:
Il est facile à lire (proche du langage humain) et fonctionne avec tout type comparable (entiers, doubles, types personnalisés ...).
Avoir un code facile à lire est important car le développeur ne perdra pas de «cycles cérébraux» pour le comprendre. Dans les longues sessions de codage, les cycles cérébraux gaspillés rendent le développeur fatigué plus tôt et sujet aux bogues.
la source
IsInRange. I'm not that keen on Ben's inclusive boolean as that requires a few more brain cycles. It has the advantage that it can be used in any class that that implements IComparer. This is in my Extensions now along with
LiesWithin /LiesInside. Just can't decide which.
NotOutside fonctionnerait mais je n'aime pas les conditions négativesAvec un peu d'abus de méthode d'extension, nous pouvons obtenir la solution «élégante» suivante:
la source
enum Inclusive
des valeurs:Lower
,Upper
,All
. Et pour passer laIn
fonction d' un paramètre supplémentaire de typeenum Inclusive
avec la valeur par défautInclusive.All
, mettez à jour leTo
corps de la fonction poignéeAll
,Lower
, lesUpper
valeurs :)Si c'est accidentel, un simple
if
est tout ce dont vous avez besoin. Si cela se produit dans de nombreux endroits, vous voudrez peut-être considérer ces deux éléments:Quelque chose comme:
la source
la source
Utiliser une
&&
expression pour joindre deux comparaisons est simplement la manière la plus élégante de le faire. Si vous essayez d'utiliser des méthodes d'extension sophistiquées et autres, vous vous demandez s'il faut inclure la limite supérieure, la limite inférieure ou les deux. Une fois que vous commencez à ajouter des variables supplémentaires ou à modifier les noms d'extension pour indiquer ce qui est inclus, votre code devient plus long et plus difficile à lire (pour la grande majorité des programmeurs). De plus, des outils comme Resharper vous avertiront si votre comparaison n'a pas de sens (number > 100 && number < 1
), ce qu'ils ne feront pas si vous utilisez une méthode ('i.IsB Between (100, 1)').Le seul autre commentaire que je ferais est que si vous vérifiez les entrées avec l'intention de lever une exception, vous devriez envisager d'utiliser des contrats de code:
C'est plus élégant que
if(...) throw new Exception(...)
, et vous pouvez même obtenir des avertissements lors de la compilation si quelqu'un essaie d'appeler votre méthode sans vous assurer que le nombre est dans les limites en premier.la source
Si vous voulez écrire plus de code qu'un simple if, vous pouvez peut-être: Créer une méthode d'extension appelée IsBetween
...
Addenda:il est intéressant de noter que dans la pratique, vous ne "vérifiez que l'égalité" (ou <,>) dans une base de code. (Sauf dans les situations les plus triviales.) À titre d'exemple, tout programmeur de jeu utiliserait des catégories quelque chose comme ce qui suit dans chaque projet, comme une question de base. Notez que dans cet exemple, il utilise (se trouve être) une fonction (Mathf.Approximately) qui est intégrée à cet environnement; dans la pratique, vous devez généralement développer soigneusement vos propres concepts sur ce que les comparaisons signifient pour les représentations informatiques de nombres réels, pour le type de situation que vous concevez. (Ne dites même pas que si vous faites quelque chose comme, peut-être un contrôleur, un contrôleur PID ou autre, tout le problème devient central et très difficile, cela devient la nature du projet.
la source
return (value >= Min && value <= Max);
Parce que toutes les autres réponses ne sont pas inventées par moi, voici juste ma mise en œuvre:
Vous pouvez ensuite l'utiliser comme ceci:
la source
MODIFIER: Nouvelle réponse fournie. Je commençais à peine à utiliser C # lorsque j'ai écrit la première réponse à cette question, et avec le recul je me rends compte maintenant que ma «solution» était / est naïve et inefficace.
Ma réponse originale: j'irais avec la version la plus simple:
if(Enumerable.Range(1,100).Contains(intInQuestion)) { ...DoStuff; }
Une meilleure façon
Comme je n'ai vu aucune autre solution plus efficace (au moins d'après mes tests), je vais essayer de nouveau.
Nouvelle et meilleure méthode qui fonctionne également avec des plages négatives :
Cela peut être utilisé avec des plages positives et négatives et par défaut sur une plage de
1..100 (inclus) et utilise
x
comme nombre à vérifier suivi d'une plage facultative définie parmin
etmax
.Ajouter des exemples pour une bonne mesure
Exemple 1:
Retour:
Exemple 2: Utilisation d'une liste de nombres entiers aléatoires entre 1 et 150
Retour:
Temps d'exécution: 0.016 seconde (s)
la source
Une nouvelle tournure sur un vieux favori:
la source
En C, si l'efficacité du temps est cruciale et que les débordements d'entiers seront bouclés, on pourrait le faire
if ((unsigned)(value-min) <= (max-min)) ...
. Si 'max' et 'min' sont des variables indépendantes, la soustraction supplémentaire pour (max-min) perdra du temps, mais si cette expression peut être précalculée au moment de la compilation, ou si elle peut être calculée une fois au moment de l'exécution pour en tester plusieurs nombres par rapport à la même plage, l'expression ci-dessus peut être calculée efficacement même dans le cas où la valeur est dans la plage (si une grande fraction de valeurs sera inférieure à la plage valide, il peut être plus rapide à utiliserif ((value >= min) && (value <= max)) ...
car elle se terminera tôt si value est inférieure à min).Avant d'utiliser une telle implémentation, cependant, comparez la machine cible d'une personne. Sur certains processeurs, l'expression en deux parties peut être plus rapide dans tous les cas puisque les deux comparaisons peuvent être effectuées indépendamment alors que dans la méthode de soustraction et de comparaison, la soustraction doit être terminée avant que la comparaison puisse s'exécuter.
la source
Que diriez-vous quelque chose comme ça?
avec la méthode d'extension comme suit (testé):
la source
Je ferais un objet Range, quelque chose comme ceci:
Ensuite, vous l'utilisez de cette façon:
De cette façon, vous pouvez le réutiliser pour un autre type.
la source
Range
objet doit utiliser laCompareTo
méthode pour comparer les éléments, pas l'<
opérateur.IComparable
et ne surcharge pas l'<
opérateur.Lorsque vous vérifiez si un «nombre» est dans une plage, vous devez être clair dans ce que vous voulez dire, et que signifie deux nombres égaux? En général, vous devriez envelopper tous les nombres à virgule flottante dans ce qu'on appelle une «boule epsilon». Ceci est fait en choisissant une petite valeur et en disant que si deux valeurs sont si proches, elles sont la même chose.
Avec ces deux aides en place et en supposant que si un nombre quelconque peut être moulé en double sans la précision requise. Tout ce dont vous aurez besoin maintenant est une énumération et une autre méthode
L'autre méthode suit:
Maintenant, c'est peut-être bien plus que ce que vous vouliez, mais cela vous empêche de traiter d'arrondi tout le temps et d'essayer de vous rappeler si une valeur a été arrondie et à quel endroit. Si vous en avez besoin, vous pouvez facilement l'étendre pour fonctionner avec n'importe quel epsilon et permettre à votre epsilon de changer.
la source
Usage
double numberToBeChecked = 7;
var result = numberToBeChecked.IsB Between (100.122);
var result = 5.IsB Between (100,120);
résultat var = 8,0.IsB Between (1,2,9,6);
la source
Si vous êtes préoccupé par le commentaire de @Daap sur la réponse acceptée et que vous ne pouvez transmettre la valeur qu'une seule fois, vous pouvez essayer l'une des solutions suivantes
ou
la source
Concernant l'élégance, le plus proche de la notation mathématique ( a <= x <= b ) améliore légèrement la lisibilité:
Pour plus d'illustration:
la source
Je cherchais une manière élégante de le faire où les limites pourraient être commutées (c'est-à-dire pas sûr de l'ordre dans lequel les valeurs sont).
Cela ne fonctionnera que sur les versions plus récentes de C # où le?: Existe
Évidemment, vous pouvez modifier les signes = pour vos besoins. Pourrait aussi avoir de la fantaisie avec le casting de type. J'avais juste besoin d'un retour flottant dans les limites (ou égal à)
la source
Élégant car il ne vous oblige pas à déterminer laquelle des deux valeurs limites est la plus élevée en premier. Il ne contient pas non plus de branches.
la source
Je ne sais pas mais j'utilise cette méthode:
Et voici comment je peux l'utiliser:
la source
Voici quelques méthodes d'extension qui peuvent aider
la source
Si c'est pour valider les paramètres de méthode, aucune des solutions ne lève ArgumentOutOfRangeException et permet une configuration facile / correcte des valeurs min / max inclusives / exclusives.
Utilisez comme ça
Je viens d'écrire ces belles fonctions. Il a également l'avantage de ne pas avoir de branchement (un seul if) pour les valeurs valides. Le plus difficile est de créer les bons messages d'exception.
la source
Vous cherchez
in [1..100]
? Ce n'est que Pascal.la source
when (number) { in 0..9 -> println("1 digit") in 10..99 -> println("2 digits") in 100..999 -> println("3 digits") }