Чи нерозумно очікувати, що будь-який () * не * викине нульовий посилання на виняток?


41

При створенні методу розширення ви можете, звичайно, назвати його по null.Але, в відміну від методу примірника виклику, виклик його на нуль НЕ має , щоб кинути NullReferenceException-> ви повинні перевірити і кинути його вручну.

Для реалізації методу розширення Linq Any()Microsoft вирішила, що вони повинні кинути ArgumentNullException( https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/AnyAll.cs ).

Мене це дратує, щоб писати if( myCollection != null && myCollection.Any() )

Чи я помиляюся, як клієнт цього коду, очікувати, що, наприклад, ((int[])null).Any()слід повернутися false?


41
у C # 6 ви можете спростити чек, якщо (myCollection? .Any () == true)
17 з 26

5
Навіть у F #, який насправді не використовує нулі, за винятком сумісності з іншими мовами .NET, null |> Seq.isEmptyкидає System.ArgumentNullException: Value cannot be null. Здається, очікується, що ви не будете передавати невизначені значення для того, що, як очікується, існує, тому все одно виняток, коли у вас є нуль. Якщо це питання ініціалізації, я б почав із порожньої послідовності замість а null.
Аарон М. Ешбах

21
Ось чому ви не повинні повертатися nullпри роботі з колекціями, а натомість використовувати порожню колекцію в цих випадках.
Бакуріу

31
Ну чому це в першу чергу нульове? Ви не хочете, щоб null вважався порожнім, оскільки він не порожній, це зовсім інше. Можливо, ви хочете, щоб він вважався порожнім у вашому випадку, але додавання такої речі до мови призводить до помилок.
користувач253751

22
Я мушу зазначити, що кожен метод LINQ наводить нульовий аргумент. Anyпросто узгоджується.
Себастьян Редл

Відповіді:


157

У мене є пакетик з п'ятьма картоплями. Чи є .Any()в мішку картопля?

" Так ", ти кажеш.<= true

Я виймаю всю картоплю і їмо їх. Чи є .Any()в мішку картопля?

" Ні ", ти кажеш.<= false

Я повністю спалюю мішок на вогні. Чи існують .Any()картопля в мішку зараз?

" Сумки немає ".<= ArgumentNullException


3
Але вакуумно, картоплі в мішку немає? Під фальшивим розуміється помилкове ... (Я не погоджуюсь, лише друга перспектива).
D. Ben Knoble

6
більш практично, хтось передає вам закриту коробку з невідомого джерела. Чи містить мішок у коробці картоплю? Мене цікавлять лише 2 сценарії - А) в коробці є пакетик, в якому є картопля, або В) в коробці немає картоплі та / або мішка. Семантично, так, є різниця між нульовим і порожнім, але 99% часу мені все одно.
dave thieben

6
Ви з'їли п’ять сирих картоплин ?? Негайно зверніться до лікаря.
Олі

3
@Олі Дан готував їх на вогні, перед їжею та використовуючи цей вогонь для спалення мішка.
Ісмаїл Мігель

3
@ D.BenKnoble: Не побачивши багажника мого автомобіля, ви готові засвідчити, що в багажнику мого автомобіля немає тіл? Ні? Яка різниця між перевіркою багажника і нічого не знайти, чи не перевірити багажник? Ви не можете просто дати свідчення зараз, оскільки ви побачили б однакову кількість тіл в будь-якому випадку? ... У цьому різниця. Ви не можете поручити щось, якщо ви не в змозі підтвердити це в першу чергу. Ви припускаєте, що ці два рівні, але це не дано. У деяких випадках може бути важлива різниця між ними.
Flater

52

По-перше, виявляється, що цей вихідний код буде кинутий ArgumentNullException, а не NullReferenceException.

Сказавши це, у багатьох випадках ви вже знаєте, що ваша колекція не є нульовою, тому що цей код викликається лише з коду, який знає, що колекція вже існує, тому вам не доведеться дуже часто вводити нульову перевірку. Але якщо ви не знаєте, що воно існує, то це має сенс перевірити, перш ніж зателефонувати Any()на нього.

Чи я помиляюся, як клієнт цього коду, очікувати, що, наприклад, ((int[])null).Any()слід повернутися false?

Так. Питання, яке Any()відповідає: "Чи містить ця колекція якісь елементи?" Якщо цієї колекції не існує, то саме питання є безглуздим; він не може ні містити, ні містити нічого, тому що його не існує.


18
@ChrisWohlert: Ваша інтуїція мене заінтригує. Ви також вважаєте, що семантично неіснуюча людина - це порожня людина, ім'я якої - порожня рядок, а вік дорівнює нулю тощо? А ви вважаєте, що набір, що містить null, еквівалентний набору, що містить порожній набір (і навпаки)?
ruakh

17
@ChrisWohlert: Очевидно, що набір може містити порожній набір; але ти, здається, віриш у це { null }і { {} }має бути рівнозначним. Я вважаю це захоплюючим; Я взагалі не можу пов'язати з цим.
ruakh

9
Чи варто .Addна nullколекції якось створити колекцію і для нас?
Матвій

13
@ChrisWohlert "A - це порожній набір. B - це набір, що містить кавун. Чи порожній? Так. Чи порожній? B? Ні? С порожній? Ухх ..."
користувач253751

16
Педантичний момент: Це не так, що в теорії множин неіснуючий набір є порожнім набором. Порожній набір існує, а будь-який неіснуючий набір - це не він (і справді, це зовсім не що, оскільки його не існує).
James_pic

22

Нуль означає відсутність інформації, а не елементів.

Ви можете розглянути питання про те, щоб уникнути нуля - наприклад, використовуйте один із вбудованих порожніх перелічених даних для представлення колекції без елементів замість null.

Якщо ви повернетеся до нуля за певних обставин, ви можете змінити це, щоб повернути порожню колекцію. (Інакше, якщо ви знайдете, що нулі повернуті бібліотечними методами (не вашими), це прикро, і я б переклав їх на нормалізацію.)

Дивіться також https://stackoverflow.com/questions/1191919/what-does-linq-return-when-the-results-are-empty


1
Це nullне означає, що жодні елементи не є справою використання розумної конвенції. Подумайте лише про рідні ОЛЕСТРИНГИ, де це насправді це означає.
Дедуплікатор

1
@Deduplicator, ви говорите про можливість об'єднання та вбудовування об'єктів Microsoft? Якщо ви згадаємо, що OLE з 90-х! Якщо дивитися більше на даний момент, багато сучасних мов (C #, Java, Swift) надають засоби для усунення / викорінення використання null.
Ерік Ейдт

2
@ErikEidt Вони роблять це частково, оскільки nullне означає "відсутність інформації". nullне має єдиного змістовного тлумачення. Натомість, справа в тому, як ви ставитесь до цього. nullіноді використовується для "відсутньої інформації", але також для "відсутність елементів", а також для "сталася помилка" або "неініціалізована" або "конфліктна інформація" або якась довільна, спеціальна річ.
Дерек Елкінс

-1. Це рішення, яке приймає розробник, а не абстрактні теорії. nullабсолютно часто використовується для позначення "немає даних". Іноді це має сенс. Інший час, ні.
jpmc26

13

Крім нульового умовного синтаксису , існує ще одна методика полегшення цієї проблеми: не дозволяйте вашій змінній ніколи не залишатися null.

Розглянемо функцію, яка приймає колекцію як параметр. Якщо для цілей функції nullі порожні еквівалентні, ви можете переконатися, що він ніколи не містить nullна початку:

public MyResult DoSomething(int a, IEnumerable<string> words)
{
    words = words ?? Enumerable.Empty<string>();

    if (!words.Any())
    {
        ...

Ви можете зробити те ж саме, коли ви отримуєте колекції з якогось іншого методу:

var words = GetWords() ?? Enumerable.Empty<string>();

(Зверніть увагу , що в тих випадках , коли у вас є контроль над функцією , як GetWordsі nullеквівалентно порожній колекції, переважно , щоб просто повернути порожню колекцію в першу чергу.)

Тепер ви можете виконати будь-яку операцію над вашим бажанням над колекцією. Це особливо корисно, якщо вам потрібно виконати багато операцій, які не вдасться під час колекції null, і у випадках, коли ви отримуєте такий самий результат, перекинувши або запитуючи порожній перелік, це дозволить ifповністю усунути умови.


12

Я помиляюся, як клієнт цього коду, очікував, що, наприклад, ((int []) null). Any () повинен повернути помилкове?

Так, просто тому, що ти перебуваєш у C # і така поведінка чітко визначена та задокументована.

Якщо ви створювали власну бібліотеку або використовували іншу мову з різною культурою виключень, тоді було б розумніше розраховувати на помилкове.

Особисто я відчуваю, що повернення помилкового - це більш безпечний підхід, який робить вашу програму більш надійною, але це принаймні дискусійно.


15
Ця "надійність" часто є ілюзією - якщо код, який генерує масив, раптово почне генерувати NULL з несподіваної причини через помилку чи іншу проблему, ваш "надійний" код приховає проблему. Іноді це правильна поведінка, але не є безпечним за замовчуванням.
GoatInTheMachine

1
@GoatInTheMachine - я не погоджуюся з тим, що це безпечний дефолт, але ти маєш рацію, що він приховує проблему і що така поведінка часом небажана. На мій досвід, приховувати проблему (або довіряти тести одиниць, щоб вирішити проблеми з іншим кодом) краще, ніж збій вашої програми, кидаючи несподівані винятки. Я маю на увазі дійсно - якщо код виклику порушений достатньо, щоб надсилати нулі, то який шанс вони належним чином обробляють винятки?
Теластин

10
Якщо щось порушено, чи це мій код, чи інший колега чи клієнт, я вважаю за краще код негайно вийшов з ладу, і люди про нього знали, ніж воно перебувало у потенційно непослідовному стані протягом невизначеного часу. Здатність зробити це, звичайно, іноді є розкішшю і не завжди доречно, але я вважаю за краще підхід.
GoatInTheMachine

1
@GoatInTheMachine - Я погоджуюся на багато речей, але колекції, як правило, різні. Ставлення до нуля як до порожньої колекції - це не дуже непослідовно чи дивно.
Теластин

8
Уявіть, що у вас є масив, заповнений з документа JSON, отриманого через веб-запит, і у виробництві у одного з клієнтів вашого API раптом виникає проблема, куди він надсилає через частково недійсний JSON, що спричиняє десаріалізацію масиву як NULL: код, у гіршому випадку, кинув виняток NULL-посилання, коли з'явився перший невдалий запит, який ви побачите під час реєстрації, а потім негайно скажіть клієнтові виправити свої зламані запити, АБО ваш код каже "о, масив порожній, нічого зробити!" і мовчки писав "кошик для покупки не мав предметів" на db протягом кількох тижнів?
GoatInTheMachine

10

Якщо повторні нульові перевірки вас дратують, ви можете створити свій власний метод розширення 'IsNullOrEmpty ()', щоб відобразити метод String за цим ім'ям і обернути як єдиний виклик, так і виклик .Any () в один виклик.

Інакше рішення, згадане @ 17 з 26 у коментарі під вашим запитанням, також коротше, ніж «стандартний» метод, і зрозуміло для всіх, хто знайомий з новим нульовим умовним синтаксисом.

if(myCollection?.Any() == true)

4
Ви також можете використовувати ?? falseзамість == true. Мені це здається більш явним (чистішим), оскільки він розглядає лише випадок null, і це насправді більше не є багатослівним. Плюс ==перевірки на булеви зазвичай викликають мій рефлекс. =)
jpmc26

2
@ jpmc26: Я мало знаю про C #. Чому myCollection?.Any()недостатньо?
Ерік Думініл

6
@EricDuminil Через те, що працює нульовий умовний оператор, myCollection?.Any()ефективно повертає нульово-булевий, а не звичайний булевий (тобто bool? Замість bool). Немає неявного перетворення з bool? до bool, і це бул, який нам потрібен у цьому конкретному прикладі (для перевірки як частини ifумови). Отже, ми повинні або явно порівнювати trueабо використовувати оператор, що поєднує null (??).
Стівен Рандс

@ jpmc26 ?? false важче читати, тоді myCollection? .Any () == true. Незалежно від рефлексу на клей, == true - це те, що ви намагаєтесь неявно перевірити. ?? false просто додає додатковий шум, і вам все одно потрібно зробити оцінку в голові щодо того, що станеться, якщо null, що null == true не вдасться, майже без того, щоб читач навіть не мав про це знати ?..
Райан Ліч

2
@RyanTheLeach Мені потрібно думати набагато важче, чи ==дійсно буде працювати. Я вже знаю , що відбувається з логічним інтуїтивно , коли він може бути тільки trueабо false; Я навіть не мушу про це думати. Але киньте nullв суміш, і тепер я повинен розібратися, чи ==правильно це. ??натомість просто виключає nullвипадок, зводячи його до trueі false, що ви вже відразу зрозуміли. Що стосується мого гаг-рефлексу, коли я вперше бачу, мій безпосередній інстинкт - просто видалити його, оскільки він зазвичай марний, чого ви не хочете, щоб це відбувалося.
jpmc26

8

Я помиляюся, як клієнт цього коду, очікував, що, наприклад, ((int []) null). Any () повинен повернути помилкове?

Якщо ви замислюєтесь над очікуванням, вам доведеться подумати про наміри.

null означає щось дуже відмінне від Enumerable.Empty<T>

Як згадується у відповіді Еріка Ейдта , різниця в значенні між nullі порожньою колекцією.

Давайте спочатку подивимось на те, як їх слід використовувати.

Книга Framework Design Guidelines: конвенції, ідіоми і шаблони для багаторазового використання .NET бібліотек, друге видання , написаного Microsoft архітекторів Кшиштоф Кваліна і Бред Абрамс стверджує наступні кращі практики:

X НЕ повертайте нульові значення з властивостей колекції або з методів повернення колекцій. Натомість поверніть порожню колекцію чи порожній масив.

Розглянемо ваш метод виклику, який в кінцевому підсумку отримує дані з бази даних: Якщо ви отримуєте порожній масив або Enumerable.Empty<T>це просто означає, що ваш вибірковий простір порожній, тобто ваш результат - порожній набір . nullОднак одержання в цьому контексті означатиме стан помилки .

У тому ж думці, що і в аналогії з картоплею Дена Вілсона , є сенс задавати питання щодо своїх даних, навіть якщо це порожній набір . Але це має набагато менший сенс, якщо немає набору .


1
Чи мають вони різні значення, дуже залежить від контексту. Часто з метою будь-якої логіки під рукою вони представляють рівнозначні поняття. Не завжди , але часто.
jpmc26

1
@ jpmc26: Я думаю, що сенс цієї відповіді полягає в тому, щоб сказати, що вказівки щодо кодування для c # вони мають інше значення. Ви завжди можете правильно вказувати код, у якому нуль і порожній - це те саме, якщо ви хочете. І в деяких випадках ви також можете робити те ж саме, будь то пусте чи порожнє, але це не означає, що вони означають те саме.
Кріс,

@Chris І я кажу, що вказівки щодо кодування людей, які розробили мову, не можна використовувати як заміну для оцінки вашого коду в контексті ваших вимог, бібліотек, якими ви користуєтесь, та інших розробників, з якими працюєте. Ідея, що вони ніколи не будуть рівнозначними в контексті, - це ідеальний ідеалізм. Вони можуть навіть не бути еквівалентними для даних, які є у вас в цілому, але є еквівалентними для отримання результату в певній функції, яку ви пишете; у такому випадку вам потрібно підтримувати обоє, але гарантувати, що вони дають однаковий результат.
jpmc26

Мене може збити з пантелику те, що ви говорите, але коли null і empty є еквівалентом для отримання результату, я не бачу, чому ви не просто використовували б окреме, це null, і це порожні чеки, а не бажаючи методу, який робить і те, і інше, але не дозволяє розрізнити їх в інших ситуаціях ...
Кріс,

@Chris Я маю на увазі наявність різних контекстів (які часто відповідають обсягам). Розглянемо, наприклад, функцію. nullі порожній може призвести до однакового зворотного значення для функції, але це не означає, що nullі порожнє означає точно те саме, що в області виклику.
jpmc26

3

Є багато відповідей, що пояснюють, чому nullі порожні різні, і достатньо думок, які намагаються пояснити обидва, чому до них слід ставитися по-різному чи ні. Однак ви запитуєте:

Я помиляюся, як клієнт цього коду, очікував, що, наприклад, ((int []) null). Any () повинен повернути помилкове?

Це цілком розумні очікування . Ви такі ж праві, як і хтось, хто виступає за поточну поведінку. Я погоджуюся з існуючою філософією впровадження, але рушійні фактори не тільки - ґрунтуються на міркуваннях поза контекстом.

Враховуючи, що Any()без присудка є по суті, Count() > 0то чого ви очікуєте від цього фрагмента?

List<int> list = null;
if (list.Count > 0) {}

Або загальне:

List<int> list = null;
if (list.Foo()) {}

Я гадаю, ви очікуєте NullReferenceException.

  • Any()це метод розширення, він повинен плавно інтегруватися з розширеним об'єктом, тоді кидання винятку - найменш дивно.
  • Не кожна мова .NET підтримує методи розширення.
  • Ви завжди можете зателефонувати, Enumerable.Any(null)і там ви напевно очікуєте ArgumentNullException. Це той самий метод, і він повинен узгоджуватися - можливо - майже з ВСЕМ іншим у рамках.
  • Доступ до nullоб'єкта - це помилка програмування , фреймворк не повинен застосовувати нуль як магічне значення . Якщо ви використовуєте його таким чином, тоді ви несете відповідальність за це.
  • Це впевнено , ти думаєш один спосіб, а я думаю інший. Рамки повинні бути максимально непідданими.
  • Якщо у вас є особливий випадок, тоді ви повинні бути послідовними : вам доведеться приймати все більше і більш впевнених рішень щодо всіх інших методів розширення: якщо це Count()здається простим рішенням, Where()це не так. Про що Max()? Він кидає виняток для списку EMPTY, чи не повинен він кидати і для nullодного?

Те, що дизайнери бібліотеки робили перед LINQ, було ввести явні методи, коли nullце дійсне значення (наприклад String.IsNullOrEmpty()), то вони HAD повинні відповідати існуючій філософії дизайну . Це сказало, навіть якщо це досить тривіально написати, два способи EmptyIfNull()і EmptyOrNull()можуть бути корисними.


1

Джим повинен залишати картоплю в кожному пакетику. Інакше я збираюся його вбити.

У Джима є мішок з п'ятьма картоплями. Чи є .Any()в мішку картопля?

"Так", ти кажеш. <= вірно

Гаразд, Джим живе на цей раз.

Джим виймає всю картоплю і їсть їх. Чи є в мішку будь-яка () картопля?

"Ні", ти кажеш. <= хибно

Час вбити Джима.

Джим повністю спалює мішок у вогні. Чи є в упаковці всяка () картопля?

"Сумки немає". <= ArgumentNullException

Чи повинен Джим жити чи померти? Ну, ми цього не очікували, тому мені потрібна ухвала. Дозволити Джиму позбутися цієї помилки чи ні?

Ви можете використовувати примітки, щоб повідомити, що таким чином ви не змиряєтесь з жодними нульовими шенагінгами.

public bool Any( [NotNull] List bag ) 

Але ваш ланцюжок інструментів повинен його підтримувати. Що означає, що ви, ймовірно, все одно закінчите писати чеки.


0

Якщо це вас так турбує, я пропоную простий метод продовження.

static public IEnumerable<T> NullToEmpty<T>(this IEnumerable<T> source)
{
    return (source == null) ? Enumerable.Empty<T>() : source;
}

Тепер ви можете зробити це:

List<string> list = null;
var flag = list.NullToEmpty().Any( s => s == "Foo" );

... і прапор встановиться на false.


2
Більш природно написати returnзаяву , як:return source ?? Enumerable.Empty<T>();
Jeppe Стіг Нільсен

Це не відповідає на поставлене запитання.
Кеннет К.

@ KennethK.but, схоже, вирішує представлену проблему.
RQDQ

0

Це питання щодо методів розширення C # та їх філософії дизайну, тому я вважаю, що найкращим способом відповісти на це питання є цитування документації MSDN про призначення методів розширення :

Методи розширення дозволяють "додавати" методи до існуючих типів без створення нового похідного типу, перекомпіляції чи іншої модифікації вихідного типу. Методи розширення - це особливий вид статичного методу, але вони називаються так, ніби вони були методами екземплярів розширеного типу. Для клієнтського коду, написаного на C #, F # та Visual Basic, немає явної різниці між викликом методу розширення та методів, які фактично визначені у типі.

Загалом, ми рекомендуємо застосовувати методи розширення економно та лише тоді, коли це потрібно. Коли це можливо, клієнтський код, який повинен поширювати існуючий тип, повинен це зробити, створивши новий тип, похідний від існуючого типу. Для отримання додаткової інформації див. Спадщина.

Використовуючи метод розширення для розширення типу, вихідний код якого ви не можете змінити, ви ризикуєте, що зміна в реалізації типу призведе до порушення способу розширення.

Якщо ви реалізуєте методи розширення для заданого типу, пам’ятайте наступні моменти:

  • Метод розширення ніколи не буде викликатися, якщо він має такий самий підпис, як метод, визначений у типі.
  • Методи розширення вводяться в область застосування на рівні простору імен. Наприклад, якщо у вас є кілька статичних класів, які містять методи розширення в єдиному просторі імен, названий Extensionsними, всі вони будуть приведені в область застосування using Extensions;директивою.

Підводячи підсумок, методи розширення призначені для додавання примірних методів до певного типу, навіть коли розробники не можуть це зробити безпосередньо. А оскільки методи екземпляра завжди замінять методи розширення, якщо вони є (якщо вони викликаються за допомогою синтаксису методу екземпляра), це слід робити лише в тому випадку, якщо ви не можете безпосередньо додати метод або розширити клас. *

Іншими словами, метод розширення повинен діяти так само, як і метод екземпляра, оскільки він може в кінцевому підсумку бути створеним методом екземпляра деяким клієнтом. А тому, що метод екземпляра повинен кидатись, якщо об’єкт, на який він викликається, є nullтаким, як і метод розширення.


* Як бічна примітка, саме така ситуація зіткнулася з дизайнерами LINQ: коли вийшов C # 3.0, вже було мільйони клієнтів, які користувалися System.Collections.IEnumerableі System.Collections.Generic.IEnumerable<T>як у своїх колекціях, так і в foreachциклі. Ці класи повертаються IEnumeratorоб'єкти , які були тільки два методи Currentі MoveNext, таким чином додаючи додаткові необхідні методи , наприклад, такі , як Count, Anyі т.д., буде порушувати ці мільйони клієнтів. Отже, щоб забезпечити цю функціональність (тим більше, що вона може бути реалізована в термінах Currentі MoveNextз відносною легкістю), вони випустили її як методи розширення, які можна застосувати до будь-якого існуючого в даний часIEnumerableНаприклад, вони також можуть бути реалізовані класами більш ефективними способами. Якби дизайнери C # вирішили випустити LINQ в перший день, це було б запропоновано як екземплярні методи IEnumerable, і вони, ймовірно, розробили б якусь систему, щоб забезпечити реалізацію цих методів інтерфейсом за замовчуванням.


0

Я думаю, що тут важливим моментом є те, що повертаючи помилкові замість того, щоб викидати виняток, ви опромінюєте інформацію, яка може бути актуальною для майбутніх читачів / модифікаторів вашого коду.

Якщо можливо, що список є недійсним, я б запропонував окремий логічний шлях для цього, оскільки в іншому випадку в майбутньому хтось може додати якусь логіку, засновану на списку (наприклад, додавання), до іншого {} вашої, якщо це призведе до небажаний виняток, що вони не мали підстав передбачати.

Козирі для читабельності та ремонтопридатності "Я повинен писати додаткову умову" кожного разу.


0

Як правило, я пишу більшу частину свого коду, щоб вважати, що абонент несе відповідальність за те, що він не передає мені нульові дані, здебільшого з причин, викладених у " Скажіть" нулю (та інших подібних публікаціях). Поняття null часто недостатньо вивчене, і з цієї причини доцільно ініціалізувати свої змінні достроково, наскільки це практично. Якщо припустити, що ви працюєте з розумним API, то в ідеалі не слід ніколи повертати нульове значення, тому вам ніколи не доведеться перевіряти наявність нуля. Суть нуля, як заявили інші відповіді, полягає в тому, щоб переконатися, що у вас є дійсний об'єкт (наприклад, «сумка»), з яким потрібно працювати, перш ніж продовжувати. Це не особливість Any, а натомість особливість мовисебе. Ви не можете виконати більшість операцій з нульовим об'єктом, оскільки він не існує. Це так, якби я попросив вас заїхати до магазину в моїй машині, за винятком того, що я не є власником машини, тож у вас немає можливості використовувати мою машину, щоб їхати до магазину. Безглуздо виконувати операцію на тому, чого буквально не існує.

Є практичні випадки використання нуля, наприклад, коли ви буквально не маєте потрібної інформації (наприклад, якщо я запитав вас, який мій вік, найімовірніший вибір, з якого ви б відповіли на даний момент, це "я не знаю ", що таке нульове значення). Однак у більшості випадків вам слід принаймні знати, чи ваші змінні ініціалізовані чи ні. Якщо ви цього не зробите, то я б рекомендував вам посилити свій код. Найперше, що я роблю в будь-якій програмі чи функції, - це ініціалізувати значення перед тим, як використовувати його. Рідко мені потрібно перевірити наявність нульових значень, тому що я можу гарантувати, що мої змінні не є нульовими. Це добра звичка входити, і чим частіше ви пам’ятаєте про ініціалізацію змінних, тим рідше вам потрібно перевіряти на нуль.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.