Ну, если Вы собираетесь представить альтернативную оптимизацию, мы можем также пойти для итератора:
static IEnumerable<DateTime> RandomDay()
{
DateTime start = new DateTime(1995, 1, 1);
Random gen = new Random();
int range = ((TimeSpan)(DateTime.Today - start)).Days;
while (true)
yield return start.AddDays(gen.Next(range));
}
Вы могли использовать его как это:
int i=0;
foreach(DateTime dt in RandomDay())
{
Console.WriteLine(dt);
if (++i == 10)
break;
}
Отсутствие возврата null объясняется тем, что вам не нужно его проверять, и, следовательно, вашему коду не нужно следовать другому пути на основе возвращаемого значения. Возможно, вы захотите проверить Шаблон пустого объекта , который предоставляет дополнительную информацию по этому поводу.
Например, если бы я определял метод в Java, который возвращал коллекцию, я обычно предпочел бы возвращать пустой collection (например, Collections.emptyList ()
), а не null, поскольку это означает, что мой клиентский код чище; например,
Collection<? extends Item> c = getItems(); // Will never return null.
for (Item item : c) { // Will not enter the loop if c is empty.
// Process item.
}
... который чище, чем:
Collection<? extends Item> c = getItems(); // Could potentially return null.
// Two possible code paths now so harder to test.
if (c != null) {
for (Item item : c) {
// Process item.
}
}
Если код выглядит примерно так:
command = get_something_to_do()
if command: # if not Null
command.execute()
Если у вас есть фиктивный объект, чей метод execute () ничего не делает, и вы возвращаете его вместо Null в соответствующих случаях, вы не необходимо проверить регистр NULL и вместо этого можно просто сделать:
get_something_to_do().execute()
Итак, здесь проблема не между проверкой на NULL и исключением, а между вызывающей стороной, которая должна обрабатывать особые случаи, не относящиеся к регистру, по-разному (каким бы то ни было образом ) или нет.
Ну, конечно, это зависит от цели метода ... Иногда лучше было бы выбросить исключение. Все зависит от случая к случаю.
Какие альтернативы вы видите для возврата null?
Я вижу два случая:
В этом случае мы могли бы: Вернуть Null или выбросить (проверенное) исключение (или, возможно, создать элемент и вернуть его)
В этом случае мы могли бы вернуть Null, вернуть пустой список или выдать исключение.
Я считаю, что return null может быть менее эффективным, чем альтернативы, потому что он требует от клиента не забывать проверять наличие null программисты забывают и кодируют
x = find();
x.getField(); // bang null pointer exception
В Java выдача проверенного исключения RecordNotFoundException позволяет компилятору напоминать клиенту о необходимости обработки регистра.
Другие варианты для этого:
возвращение некоторого значения, которое указывает на успех или нет (или тип ошибки), но если вам просто нужно логическое значение, которое будет указывать на успех / неудачу, возврат null для неудачи, а объект для успеха не будет менее правильным, тогда возврат true / false и получение объекта через параметр.
Другой подход - использовать исключение для указания сбоев, но здесь на самом деле гораздо больше голосов, которые говорят, что это ПЛОХОЙ метод (поскольку использование исключений может быть удобным, но имеет много недостатков).
Поэтому я лично не вижу ничего плохого в том, чтобы возвращать null как указание на то, что что-то пошло не так, и проверять это позже (чтобы узнать, удалось ли вам это или нет). Кроме того, слепо полагая, что ваш метод не вернет NULL, а затем основывает свой код на нем, может привести к другим, иногда трудным для поиска ошибкам (хотя в большинстве случаев это просто приведет к сбою вашей системы :), как вы будете ссылаться на 0x00000000 рано или поздно).
Заставить их вызвать другой метод постфактум, чтобы выяснить, был ли предыдущий вызов нулевым. ;-) Привет, это было достаточно хорошо для JDBC
Иногда возвращение NULL является правильным решением, но особенно когда вы имеете дело с последовательностями различные виды (массивы, списки, строки, что у вас есть), вероятно, лучше вернуть последовательность нулевой длины, так как это приводит к более короткому и, надеюсь, более понятному коду, не требуя при этом гораздо большего количества написания со стороны разработчика API.
Для определенных сценариев вы хотите заметить сбой, как только он произойдет.
Проверка на NULL, а не утверждение (для ошибок программиста) или выдача (для ошибок пользователя или вызывающего абонента) в случай сбоя может означать, что последующие сбои труднее отследить, потому что исходный случайный случай не был обнаружен.
Более того, игнорирование ошибок может привести к уязвимостям безопасности. Возможно, пустота возникла из-за того, что буфер был перезаписан или что-то подобное. Теперь у вас не происходит сбой , что означает, что у злоумышленника есть шанс выполнить код в вашем коде.
Непреднамеренные нулевые функции могут возникать во время разработки сложных программ, и, как мертвый код, такие случаи указывают на серьезные недостатки в структуре программы.
Нулевые функции или методы часто используются в качестве поведение по умолчанию обнаруживаемой функции или заменяемого метода в объектной среде.
Добрый день,
Возвращение NULL, когда вы не можете создать новый объект, является стандартной практикой для многих API.
Почему, черт возьми, это плохой дизайн, я понятия не имею.
Править: Это верно для языков, где у вас нет исключений, таких как C, где это было условием в течение многих лет.
HTH
'Avahappy,
Нормально возвращать null, если это имеет какое-то значение:
public String getEmployeeName(int id){ ..}
В таком случае имеет смысл возвращать null, если идентификатор не соответствует существующей сущности, поскольку он позволяет отличить случай, когда совпадение не было найдено, от допустимой ошибки.
Люди могут подумать, что это плохо, потому что им можно злоупотреблять как «специальное» возвращаемое значение, указывающее на состояние ошибки, что не очень хорошо, это немного похоже на возврат кодов ошибок из функции, но сбивает с толку, потому что пользователь должен проверять возвращаемый результат на нуль, вместо того, чтобы перехватывать соответствующие исключения, например
public Integer getId(...){
try{ ... ; return id; }
catch(Exception e){ return null;}
}
Исключения составляют исключение при любых обстоятельствах.
Если ваша функция предназначена для поиска атрибута, связанного с данным объектом, и этот объект не имеет такого атрибута, может быть уместным вернуть null. Если объект не существует, может быть более подходящим создание исключения. Если функция предназначена для возврата списка атрибутов, а возврата нет, то возврат пустого списка имеет смысл - вы возвращаете все нулевые атрибуты.
Если вы прочитаете все ответы, станет ясно, что ответ на этот вопрос зависит от типа метода.
Во-первых, когда происходит что-то исключительное (проблема ввода-вывода и т. Д.), Логически генерируются исключения. Когда именно что-то является исключительным, это, вероятно, для другой темы ..
Каждый раз, когда ожидается, что метод может не дать результатов, есть две категории:
Пока у нас нет официального способа обозначить, что функция может или не может возвращать null, я стараюсь иметь соглашение об именах обозначить так.
Так же, как у вас есть соглашение Try Something () для методов, которые, как ожидается, завершатся ошибкой, я часто называю свои методы Safe Something () , когда метод возвращает нейтральный результат вместо нуля.
Я еще не совсем согласен с названием, но ничего лучшего придумать не мог. Так что я пока этим занимаюсь.
Исходя из того, что вы сказали, я думаю, что информации недостаточно.
Возврат null из метода CreateWidget () кажется плохим.
Возврат null из метода FindFooInBar () кажется нормальным.
Это зависит от языка, который вы используете. Если вы работаете в таком языке, как C #, где идиоматический способ указать отсутствие значения - это вернуть null, тогда возврат null - хороший вариант, если у вас нет значения. С другой стороны, в таких языках, как Haskell, которые идиоматически используют монаду Maybe для этого случая, возвращение null было бы плохим дизайном (если бы это было вообще возможно).
Кто сказал, что это плохой дизайн?
Проверка на нули - обычная практика, даже поощряемая , иначе вы рискуете получить исключения NullReferenceExceptions повсюду. Лучше аккуратно обработать ошибку, чем генерировать исключения, когда в этом нет необходимости.
fts
имеет приятный интерфейс, но это 4.4BSD и не переносится. (Недавно меня укусило какое-то программное обеспечение, зависящее от fts.) opendir
и readdir
менее забавны, но соответствуют стандартам POSIX и переносимы.
Вот причина.
В Чистый код Роберта Мартина он пишет, что возврат null - это плохой дизайн, когда вы можете вместо этого вернуть, скажем, пустой массив. Поскольку ожидаемый результат - это массив, почему бы и нет? Это позволит вам перебрать результат без каких-либо дополнительных условий. Если это целое число, может быть достаточно 0, если это хеш, пустой хеш. и т.д.
Предпосылка состоит в том, чтобы не заставлять вызывающий код немедленно обрабатывать проблемы. Вызывающий код может не интересоваться ими. Вот почему во многих случаях исключения лучше, чем ноль.
Это не обязательно плохой дизайн - как и в случае со многими другими дизайнерскими решениями, это зависит.
Если результат метода не даст хорошего результата при нормальном использовании, возвращается null - это нормально:
object x = GetObjectFromCache(); // return null if it's not in the cache
Если действительно всегда должен быть ненулевой результат, тогда может быть лучше выбросить исключение:
try {
Controller c = GetController(); // the controller object is central to
// the application. If we don't get one,
// we're fubar
// it's likely that it's OK to not have the try/catch since you won't
// be able to really handle the problem here
}
catch /* ... */ {
}