Wie kann ich das elegant mit C # und .NET 3.5 / 4 machen?
Beispielsweise kann eine Zahl zwischen 1 und 100 liegen.
Ich weiß, ein einfaches Wenn würde ausreichen; aber das Schlüsselwort zu dieser Frage ist Eleganz. Es ist für mein Spielzeugprojekt nicht für die Produktion.
Bei diesen Fragen ging es nicht um Geschwindigkeit, sondern um Code-Schönheit. Hör auf über Effizienz und so zu reden; Denken Sie daran, Sie predigen vor dem Chor.
if
es nicht "Barock" ist, beheben Sie es nicht.Antworten:
Es gibt viele Möglichkeiten:
Schauen Sie sich auch diesen SO-Beitrag für Regex-Optionen an.
quelle
if
Aussage. Dies erreicht sicherlich, dass ...;)Meinst du?
oder
quelle
Um das Rauschen hier zu verstärken, können Sie eine Erweiterungsmethode erstellen:
Welches würde Sie so etwas tun lassen ...
Davon abgesehen scheint dies eine dumme Sache zu sein, wenn der Scheck selbst nur eine Zeile ist.
quelle
Verwenden Sie, wie andere sagten, ein einfaches if.
Sie sollten über die Bestellung nachdenken.
z.B
ist leichter zu lesen als
quelle
1 <= x <= 100
.=
statt eingegeben haben==
. Es hilft nicht bei relationalen Operatoren, die nicht gleich sind - aber es ist leicht, sich daran zu gewöhnen, es konsequent zu verwenden.x
einen komplexen Funktionsaufruf oder einen zeitaufwändigen Linq-Ausdruck. In diesem Fall würden Sie dies zweimal tun, was keine gute Sache ist. Sicher, Sie sollten den Wert in einer temporären lokalen Variablen speichern, aber es gibt einige Fälle (z. B. in else-if-Anweisungen), in denen Sie die Funktionen nur nach anderen if- oder else-if-Fehlern aufrufen möchten. Bei temporären Variablen müssen Sie diese trotzdem vorher aufrufen. Eine Erweiterungsmethode (in anderen Antworten erwähnt) ist in diesen Fällen die beste Lösung.Im Produktionscode würde ich einfach schreiben
Dies ist leicht zu verstehen und sehr gut lesbar.
Hier ist eine clevere Methode, mit der Sie die Anzahl der Vergleiche mithilfe von Mathematik von zwei auf eins reduzieren können. Die Idee ist, dass einer der beiden Faktoren negativ wird, wenn die Zahl außerhalb des Bereichs liegt, und Null, wenn die Zahl gleich einer der Grenzen ist:
Wenn die Grenzen inklusive sind:
oder
Wenn die Grenzen exklusiv sind:
oder
quelle
1 < x && x < 100
in produktiven Code verwenden. Es ist leichter zu verstehen.1 < x & x < 100
(kein && Kurzschluss) den Compiler an, dass er immer auswerten kann,x < 100
unabhängig vom Ergebnis von1 < x
. Seltsamerweise ist es (aufgrund der Verzweigungsvorhersage) schneller, diese einfache Operation immer auszuführen, als sie manchmal zu überspringen.Ich schlage vor:
Beispiele:
und natürlich mit Variablen:
Es ist leicht zu lesen (nahe an der menschlichen Sprache) und funktioniert mit jedem vergleichbaren Typ (ganzzahlige, doppelte, benutzerdefinierte Typen ...).
Es ist wichtig, dass der Code einfach zu lesen ist, da der Entwickler keine "Gehirnzyklen" verschwendet, um ihn zu verstehen. In langen Codierungssitzungen machen verschwendete Gehirnzyklen Entwickler früher müde und anfällig für Fehler.
quelle
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 geändert, aber ich mag keine negativen BedingungenMit ein wenig Missbrauch der Erweiterungsmethode können wir die folgende "elegante" Lösung erhalten:
quelle
enum Inclusive
mit Werten:Lower
,Upper
,All
. Und Pass für dieIn
Funktion einen zusätzlichen Parameter des Typsenum Inclusive
mit StandardwertInclusive.All
, aktualisieren Sie dieTo
Funktion Körper GriffAll
,Lower
,Upper
Werte :)Wenn dies zufällig ist, ist ein einfaches
if
alles, was Sie brauchen. Wenn dies an vielen Stellen passiert, sollten Sie diese beiden Punkte berücksichtigen:Etwas wie:
quelle
quelle
Die Verwendung eines
&&
Ausdrucks zum Verbinden zweier Vergleiche ist einfach die eleganteste Methode, um dies zu tun. Wenn Sie versuchen, ausgefallene Erweiterungsmethoden und dergleichen zu verwenden, stellen Sie sich die Frage, ob die Obergrenze, die Untergrenze oder beides eingeschlossen werden soll. Sobald Sie zusätzliche Variablen hinzufügen oder die Erweiterungsnamen ändern, um anzugeben, was enthalten ist, wird Ihr Code länger und schwerer zu lesen (für die überwiegende Mehrheit der Programmierer). Darüber hinaus werden Sie von Tools wie Resharper gewarnt, wenn Ihr Vergleich keinen Sinn ergibt (number > 100 && number < 1
), was sie nicht tun, wenn Sie eine Methode verwenden ('i.IsBetween (100, 1)').Der einzige andere Kommentar, den ich machen möchte, ist, dass Sie, wenn Sie Eingaben mit der Absicht überprüfen, eine Ausnahme auszulösen, die Verwendung von Codeverträgen in Betracht ziehen sollten:
Das ist eleganter als
if(...) throw new Exception(...)
, und Sie könnten sogar Warnungen zur Kompilierungszeit erhalten, wenn jemand versucht, Ihre Methode aufzurufen, ohne sicherzustellen, dass die Nummer zuerst in Grenzen liegt.quelle
Wenn Sie mehr Code als ein einfaches if schreiben möchten, können Sie möglicherweise: Eine Erweiterungsmethode namens IsBetween erstellen
...
Nachtrag:Es ist erwähnenswert, dass Sie in der Praxis sehr selten "nur auf Gleichheit prüfen" (oder <,>) in einer Codebasis. (Anders als in den trivialsten Situationen.) Als Beispiel würde jeder Spielprogrammierer in jedem Projekt grundsätzlich Kategorien wie die folgenden verwenden. Beachten Sie, dass in diesem Beispiel eine Funktion (Mathf.Approximate) verwendet wird, die in diese Umgebung integriert ist. In der Praxis müssen Sie in der Regel sorgfältig Ihre eigenen Konzepte entwickeln, was Vergleiche für Computerdarstellungen von reellen Zahlen bedeuten, für die Art der Situation, in der Sie sich befinden. (Erwähnen Sie nicht einmal, dass, wenn Sie so etwas wie einen Regler, einen PID-Regler oder ähnliches tun, das ganze Problem zentral und sehr schwierig wird, es wird zur Natur des Projekts.
quelle
return (value >= Min && value <= Max);
Weil alle anderen Antworten nicht von mir erfunden wurden, hier nur meine Implementierung:
Sie können es dann folgendermaßen verwenden:
quelle
BEARBEITEN: Neue Antwort bereitgestellt. Ich habe gerade mit C # angefangen, als ich die erste Antwort auf diese Frage schrieb, und im Nachhinein stelle ich jetzt fest, dass meine "Lösung" naiv und ineffizient war / ist.
Meine ursprüngliche Antwort: Ich würde mit der einfacheren Version gehen:
if(Enumerable.Range(1,100).Contains(intInQuestion)) { ...DoStuff; }
Ein besserer Weg
Da ich keine andere Lösung gesehen habe, die effizienter ist (zumindest nach meinen Tests), werde ich es noch einmal versuchen.
Neuer und besserer Weg, der auch mit negativen Bereichen funktioniert :
Dies kann sowohl mit positiven als auch mit negativen Bereichen verwendet werden und ist standardmäßig auf einen Bereich von eingestellt
1..100 (einschließlich) und wird
x
als zu prüfende Nummer verwendet, gefolgt von einem optionalen Bereich, der durchmin
und definiert istmax
.Hinzufügen von Beispielen für eine gute Maßnahme
Beispiel 1:
Kehrt zurück:
Beispiel 2: Verwenden einer Liste zufälliger Ints zwischen 1 und 150
Kehrt zurück:
Ausführungszeit: 0,016 Sekunde (n)
quelle
Eine neue Variante eines alten Favoriten:
quelle
In C könnte man dies tun, wenn die Zeiteffizienz entscheidend ist und ganzzahlige Überläufe umlaufen
if ((unsigned)(value-min) <= (max-min)) ...
. Wenn 'max' und 'min' unabhängige Variablen sind, verschwendet die zusätzliche Subtraktion für (max-min) Zeit, aber wenn dieser Ausdruck zur Kompilierungszeit vorberechnet werden kann oder wenn er zur Laufzeit einmal berechnet werden kann, um viele zu testen Bei Zahlen für denselben Bereich kann der obige Ausdruck auch dann effizient berechnet werden, wenn der Wert innerhalb des Bereichs liegt (wenn ein großer Teil der Werte unter dem gültigen Bereich liegt, ist die Verwendung möglicherweise schneller,if ((value >= min) && (value <= max)) ...
da er bei einem Wert vorzeitig beendet wird ist kleiner als min).Bevor Sie jedoch eine solche Implementierung verwenden, sollten Sie einen Benchmark für den eigenen Zielcomputer durchführen. Auf einigen Prozessoren kann der zweiteilige Ausdruck in allen Fällen schneller sein, da die beiden Vergleiche unabhängig voneinander durchgeführt werden können, während bei der Subtraktions- und Vergleichsmethode die Subtraktion abgeschlossen sein muss, bevor der Vergleich ausgeführt werden kann.
quelle
Wie wäre es mit so etwas?
mit der Erweiterungsmethode wie folgt (getestet):
quelle
Ich würde ein Range-Objekt erstellen, ungefähr so:
Dann verwenden Sie es folgendermaßen:
Auf diese Weise können Sie es für einen anderen Typ wiederverwenden.
quelle
Range
Objekt muss dieCompareTo
Methode zum Vergleichen von Elementen verwenden, nicht den<
Operator.IComparable
den<
Bediener implementiert und nicht überlastet .Wenn Sie prüfen, ob sich eine "Zahl" in einem Bereich befindet, müssen Sie sich darüber im Klaren sein, was Sie meinen, und was bedeuten zwei Zahlen gleich viel? Im Allgemeinen sollten Sie alle Gleitkommazahlen in eine sogenannte "Epsilon-Kugel" einschließen. Dies geschieht, indem Sie einen kleinen Wert auswählen und sagen, wenn zwei Werte so nahe beieinander liegen, sind sie dasselbe.
Mit diesen beiden Helfern an Ort und Stelle und unter der Annahme, dass eine beliebige Zahl ohne die erforderliche Genauigkeit als Doppel gewirkt werden kann. Jetzt brauchen Sie nur noch eine Aufzählung und eine andere Methode
Die andere Methode folgt:
Das ist vielleicht weit mehr als das, was Sie wollten, aber es hält Sie davon ab, sich ständig mit Rundungen zu befassen und sich zu erinnern, ob und an welcher Stelle ein Wert gerundet wurde. Wenn nötig, können Sie dies problemlos erweitern, um mit jedem Epsilon zu arbeiten und um zu ermöglichen, dass sich Ihr Epsilon ändert.
quelle
Verwendung
double numberToBeChecked = 7;
var result = numberToBeChecked.IsBetween (100,122);
var result = 5.IsBetween (100,120);
var result = 8.0.IsBetween (1.2,9.6);
quelle
Wenn Sie sich mit dem Kommentar von @Daap zur akzeptierten Antwort befassen und den Wert nur einmal übergeben können, können Sie eine der folgenden Möglichkeiten ausprobieren
oder
quelle
In Bezug auf Eleganz verbessert das, was der mathematischen Notation am nächsten kommt ( a <= x <= b ), die Lesbarkeit geringfügig:
Zur weiteren Veranschaulichung:
quelle
Ich suchte nach einer eleganten Möglichkeit, um die Grenzen zu ändern (dh nicht sicher, in welcher Reihenfolge sich die Werte befinden).
Dies funktioniert nur bei neueren Versionen von C #, bei denen das?: Vorhanden ist
Natürlich können Sie die Zeichen dort für Ihre Zwecke ändern. Könnte auch beim Typguss ausgefallen sein. Ich brauchte nur einen Float Return innerhalb von Grenzen (oder gleich)
quelle
Elegant, da Sie nicht zuerst bestimmen müssen, welcher der beiden Grenzwerte größer ist. Es enthält auch keine Zweige.
quelle
Ich weiß es nicht, aber ich benutze diese Methode:
Und so kann ich es benutzen:
quelle
Dies sind einige Erweiterungsmethoden, die helfen können
quelle
Wenn Methodenparameter validiert werden sollen, löst keine der Lösungen ArgumentOutOfRangeException aus und ermöglicht eine einfache / ordnungsgemäße Konfiguration von Inklusiv- / Exklusiv-Min / Max-Werten.
Verwenden Sie so
Ich habe gerade diese schönen Funktionen geschrieben. Es hat auch den Vorteil, dass keine Verzweigung (ein einzelnes Wenn) für gültige Werte vorliegt. Am schwierigsten ist es, die richtigen Ausnahmemeldungen zu erstellen.
quelle
Sie suchen
in [1..100]
? Das ist nur Pascal.quelle
when (number) { in 0..9 -> println("1 digit") in 10..99 -> println("2 digits") in 100..999 -> println("3 digits") }