Как я могу сделать это элегантно с C # и .NET 3.5 / 4?
Например, число может быть от 1 до 100.
Я знаю простой, если будет достаточно; но ключевое слово в этом вопросе - элегантность. Это для моего игрушечного проекта, а не для производства.
Этот вопрос был не о скорости, а о красоте кода. Хватит говорить об эффективности и тому подобном; помните, что вы проповедуете хору.
if
не "барокко", не исправляйте это.Ответы:
Вариантов много:
Кроме того, проверьте этот SO пост для опций регулярных выражений.
источник
if
заявление. Это, безусловно, делает это ...;)Ты имеешь ввиду?
или
источник
Просто чтобы добавить шум, вы можете создать метод расширения:
Что позволит вам сделать что-то вроде ...
Это, как говорится, кажется глупым, когда проверка состоит из одной строки.
источник
Как говорили другие, используйте простой if.
Вы должны подумать о заказе.
например
легче читать, чем
источник
1 <= x <= 100
.=
вместо==
. Это не помогает с реляционными операторами неравенства - но легко привыкнуть к его последовательному использованию.x
сложный вызов функции или трудоемкое Linq-выражение. В этом случае вы бы сделали это дважды, что не очень хорошая вещь. Конечно, вы должны сохранить значение во временной локальной переменной, но в некоторых случаях (например, в выражениях else-if-if) вы хотите вызывать функции только после сбоя if, if или else-if. С временными переменными вы должны вызывать их в любом случае раньше. Метод расширения (упомянутый в других ответах) является лучшим решением imho в этих случаях.В производственном коде я бы просто написал
Это легко понять и очень легко прочитать.
Вот умный метод, который уменьшает количество сравнений с двух до одного, используя некоторую математику. Идея состоит в том, что один из двух факторов становится отрицательным, если число лежит за пределами диапазона, и ноль, если число равно одной из границ:
Если границы включены:
или
Если границы являются исключительными:
или
источник
1 < x && x < 100
продуктивный код. Это легче понять.1 < x & x < 100
(без && короткого замыкания) указывает компилятору, что он всегда может оценитьx < 100
независимо от результата1 < x
. Как ни странно (из-за предсказания ветвлений) всегда проще выполнить эту простую операцию, чем иногда ее пропустить.Я предлагаю это:
Примеры:
и конечно с переменными:
Он легко читается (близок к человеческому языку) и работает с любым сопоставимым типом (целое, двойное, пользовательские типы ...).
Важно, чтобы код был легко читаемым, потому что разработчик не будет тратить «мозговые циклы» на его понимание. В долгих сеансах кодирования потраченные впустую мозговые циклы утомляют разработчика раньше и склонны к ошибкам.
источник
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 будет работать, но я не люблю негативные условияНемного злоупотребив методом расширения, мы можем получить следующее «элегантное» решение:
источник
enum Inclusive
со значениями:Lower
,Upper
,All
. И передать дляIn
функции одного дополнительного параметра типаenum Inclusive
с Значением по умолчаниюInclusive.All
, обновлениеTo
тела функции ручкиAll
,Lower
,Upper
значение :)Если это случайно, просто
if
все, что вам нужно. Если это происходит во многих местах, вы можете рассмотреть эти два:Что-то вроде:
источник
источник
Использование
&&
выражения для объединения двух сравнений - это просто самый элегантный способ сделать это. Если вы попытаетесь использовать причудливые методы расширения и тому подобное, вы столкнетесь с вопросом: включать ли верхнюю границу, нижнюю границу или и то, и другое. Как только вы начинаете добавлять дополнительные переменные или изменять имена расширений, чтобы указать, что включено, ваш код становится длиннее и труднее для чтения (для подавляющего большинства программистов). Более того, такие инструменты, как Resharper, будут предупреждать вас, если ваше сравнение не имеет смысла (number > 100 && number < 1
), что они не будут делать, если вы используете метод ('i.IsBetween (100, 1)').Единственный другой комментарий, который я хотел бы сделать, заключается в том, что если вы проверяете входные данные с намерением вызвать исключение, вам следует рассмотреть возможность использования контрактов кода:
Это более элегантно
if(...) throw new Exception(...)
, и вы даже можете получить предупреждения во время компиляции, если кто-то попытается вызвать ваш метод, не убедившись, что число находится в пределах границ.источник
Если вы хотите написать больше кода, чем простой if, возможно, вы можете: Создать метод расширения с именем IsBetween
...
Приложение:Стоит отметить, что на практике вы очень редко «просто проверяете на равенство» (или <,>) в кодовой базе. (За исключением самых тривиальных ситуаций.) Чисто в качестве примера, любой программист игры будет использовать категории, подобные приведенным ниже, в каждом проекте в качестве основного вопроса. Обратите внимание, что в этом примере (случается, что) используется функция (Mathf.Approximately), которая встроена в эту среду; на практике вам, как правило, приходится тщательно разрабатывать свои собственные представления о том, что означает сравнение для компьютерного представления действительных чисел, для типа ситуации, которую вы разрабатываете. (Даже не упоминайте, что если вы делаете что-то вроде, например, контроллера, ПИД-регулятора или чего-то подобного, весь вопрос становится центральным и очень сложным, он становится природой проекта.
источник
return (value >= Min && value <= Max);
Потому что все остальные ответы не придуманы мной, вот только моя реализация:
Затем вы можете использовать его так:
источник
РЕДАКТИРОВАТЬ: Новый ответ при условии. Я только начинал использовать C #, когда написал первый ответ на этот вопрос, и теперь я понимаю, что мое «решение» было / наивно и неэффективно.
Мой оригинальный ответ: я бы пошел с более простой версией:
if(Enumerable.Range(1,100).Contains(intInQuestion)) { ...DoStuff; }
Лучший путь
Поскольку я не видел ни одного другого более эффективного решения (по крайней мере, согласно моим тестам), я попробую еще раз.
Новый и лучший способ, который также работает с отрицательными диапазонами :
Это может использоваться как с положительным, так и с отрицательным диапазоном, а по умолчанию используется диапазон
1..100 (включительно) и использует
x
в качестве номера для проверки, за которым следует необязательный диапазон, определяемыйmin
иmax
.Добавление примеров для хорошей меры
Пример 1:
Возвращает:
Пример 2. Использование списка случайных чисел от 1 до 150
Возвращает:
Время выполнения: 0,016 секунды
источник
Новый поворот в старых любимых:
источник
В C, если эффективность времени имеет решающее значение и целочисленные переполнения будут обернуты, это можно сделать
if ((unsigned)(value-min) <= (max-min)) ...
. Если 'max' и 'min' являются независимыми переменными, дополнительное вычитание для (max-min) будет тратить время, но если это выражение можно предварительно вычислить во время компиляции или если его можно вычислить один раз во время выполнения, чтобы проверить множество числа против одного и того же диапазона, вышеупомянутое выражение может быть эффективно вычислено даже в случае, когда значение находится в пределах диапазона (если большая часть значений будет ниже допустимого диапазона, это может быть быстрее использовать,if ((value >= min) && (value <= max)) ...
потому что это выйдет рано если значение меньше, чем мин).Прежде чем использовать такую реализацию, сравните с целевой машиной. На некоторых процессорах выражение из двух частей может быть быстрее во всех случаях, так как два сравнения могут быть выполнены независимо, тогда как в методе вычитания и сравнения вычитание должно быть выполнено до того, как сравнение может быть выполнено.
источник
Как насчет этого?
с методом расширения следующим образом (проверено):
источник
Я бы сделал объект Range, что-то вроде этого:
Тогда вы используете это так:
Таким образом, вы можете использовать его для другого типа.
источник
Range
объект должен использоватьCompareTo
метод для сравнения элементов, а не<
оператор.IComparable
и не перегружать<
оператора.При проверке, находится ли «число» в диапазоне, вы должны четко понимать, что вы имеете в виду, и что означают два равных числа? В общем, вы должны обернуть все числа с плавающей запятой в так называемый «эпсилон-шар», это делается путем выбора небольшого значения и указания, что если два значения находятся так близко, это одно и то же.
С этими двумя помощниками на месте и предполагая, что если любое число может быть брошено как двойное без необходимой точности. Все, что вам нужно сейчас, это перечисление и другой метод
Другой метод следующий:
Теперь это может быть намного больше, чем вы хотели, но это мешает вам постоянно заниматься округлением и пытаться вспомнить, округлено ли значение и до какого места. Если вам нужно, вы можете легко расширить это для работы с любым эпсилоном и позволить вашему эпсилону измениться.
источник
использование
double numberToBeChecked = 7;
var result = numberToBeChecked.IsBetween (100,122);
var result = 5.IsBetween (100,120);
var result = 8.0.IsBetween (1.2,9.6);
источник
Если вас беспокоит комментарий @Daap о принятом ответе, и вы можете передать значение только один раз, попробуйте один из следующих вариантов.
или
источник
Что касается элегантности, то самая близкая вещь к математической записи ( a <= x <= b ) немного улучшает читабельность:
Для дальнейшей иллюстрации:
источник
Я искал элегантный способ сделать это, где границы могут быть переключены (т.е. не уверен, в каком порядке находятся значения).
Это будет работать только на более новых версиях C #, где существует::
Очевидно, вы могли бы изменить знаки = там для ваших целей. Могли бы получить фантазию с типом литья тоже. Мне просто нужно возвращение с плавающей точкой в пределах (или равно)
источник
Элегантно, потому что не требует, чтобы вы определили, какое из двух граничных значений больше. Он также не содержит ветвей.
источник
Я не знаю, но я использую этот метод:
И вот как я могу использовать это:
источник
Вот некоторые методы расширения, которые могут помочь
источник
Если это проверка параметров метода, ни одно из решений не выдает исключение ArgumentOutOfRangeException и позволяет легко / правильно настроить включающие / исключающие минимальные / максимальные значения.
Используйте как это
Я просто написал эти прекрасные функции. Он также имеет то преимущество, что не имеет разветвления (единственное if) для допустимых значений. Самое сложное - создать правильные сообщения об исключениях.
источник
Вы ищете
in [1..100]
? Это только Паскаль.источник
when (number) { in 0..9 -> println("1 digit") in 10..99 -> println("2 digits") in 100..999 -> println("3 digits") }