Possible NullReferenceException...
От: Shmj Ниоткуда  
Дата: 15.07.21 07:41
Оценка:
Такой вопрос, немного с философским уклоном.

Вот, вы выделяете некие данные через LINQ2XML.

Согласно протоколу элемент в документе обязательно существует и его отсутствие — не есть допустимо. Однако же шибко вумный подсказчик ничего не знает о протоколе и как бы говорит проблему — вот тут у вас типа NullReferenceException может возникнуть:



Как удовлетворить подсказчика и при этом не писать много лишнего кода?

Он же рекомендует conditional access. Однако это значит, что я допускаю значение null и это типа ожидаемое значение, но на самом деле нет.

Как сделать?
Re: <Nullable>enable</Nullable>
От: Qbit86 Кипр
Дата: 15.07.21 07:51
Оценка: 34 (5) +2
Здравствуйте, Shmj, Вы писали:

S>Как удовлетворить подсказчика и при этом не писать много лишнего кода?


В C# 8 для подавления ложных срабатываний используется восклицательный знак:
XElement? element = xDocument.Root!.Element("group");


В C# 7.3 можно использовать ассерт; Rider в этом случае перестаёт жаловаться:
Debug.Assert(xDocument.Root != null);
XElement element = xDocument.Root.Element("group");
Глаза у меня добрые, но рубашка — смирительная!
Отредактировано 15.07.2021 7:56 Qbit86 . Предыдущая версия . Еще …
Отредактировано 15.07.2021 7:53 Qbit86 . Предыдущая версия .
Re[2]: <Nullable>enable</Nullable>
От: Sharov Россия  
Дата: 15.07.21 11:11
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>В C# 7.3 можно использовать ассерт; Rider в этом случае перестаёт жаловаться:

Q>
Q>Debug.Assert(xDocument.Root != null);
Q>XElement element = xDocument.Root.Element("group");
Q>



В R# можно в единичном\в классе\в файле убрать соотв. warning'и.
Кодом людям нужно помогать!
Re: Possible NullReferenceException...
От: Ночной Смотрящий Россия  
Дата: 15.07.21 14:07
Оценка: +1
Здравствуйте, Shmj, Вы писали:

S>Согласно протоколу элемент в документе обязательно существует


Какому протоколу?

S>и его отсутствие — не есть допустимо.


Тем не менее пустой документ имеет это свойство равным null.

S> Однако же шибко вумный подсказчик ничего не знает о протоколе


Шибко вумный подсказчик все прекрасно знает про конкретный класс, потому что в разметке этого класса явно сказано, что свойство может быть равным null.

S>Как удовлетворить подсказчика и при этом не писать много лишнего кода?


Проверять на null.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[2]: Possible NullReferenceException...
От: Shmj Ниоткуда  
Дата: 16.07.21 06:32
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

S>>Согласно протоколу элемент в документе обязательно существует

НС>Какому протоколу?

Согласно протоколу обмена, т.е. соглашениям с тем, кто этот XML-документ предоставляет.

S>>и его отсутствие — не есть допустимо.

НС>Тем не менее пустой документ имеет это свойство равным null.

Там не может быть пустого документа — при попытке распарсить пустую строку — возникает исключение.

S>>Как удовлетворить подсказчика и при этом не писать много лишнего кода?

НС>Проверять на null.

Так там внутри запроса этих проверок с десяток будет. Зачем дублировать код?
Re[2]: <Nullable>enable</Nullable>
От: Shmj Ниоткуда  
Дата: 16.07.21 06:33
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>В C# 7.3 можно использовать ассерт; Rider в этом случае перестаёт жаловаться:

Q>
Q>Debug.Assert(xDocument.Root != null);
Q>XElement element = xDocument.Root.Element("group");
Q>


А если внутри запроса те же варнинги с десяток? Там же не только Root но и .Element("group") может быть null.
Re[3]: <Nullable>enable</Nullable>
От: yenik  
Дата: 16.07.21 07:48
Оценка:
Q>>В C# 7.3 можно использовать ассерт; Rider в этом случае перестаёт жаловаться:
Q>>
Q>>Debug.Assert(xDocument.Root != null);
Q>>XElement element = xDocument.Root.Element("group");
Q>>


S>А если внутри запроса те же варнинги с десяток? Там же не только Root но и .Element("group") может быть null.


Перейти на C# 8 никак? Тогда можно было бы использовать "!".
Re[3]: Explicit check
От: Qbit86 Кипр
Дата: 16.07.21 08:20
Оценка: +1
Здравствуйте, Shmj, Вы писали:

S>Там же не только Root но и .Element("group") может быть null.


Э нет, вот этих ребят я бы уже по-честному проверял на null, чтобы явно обработать это в коде. Можно даже как-нибудь вычурно через паттерн-матчинг:
if (xDocument.Root.Element("group") is XElement groupElement)
{
    ...
}


S>А если внутри запроса те же варнинги с десяток?


Можно через resharper_possible_null_reference_exception_highlighting [1] в EditorConfig [2] для всего файла, или через комментарии в узком скоупе:
// ReSharper disable PossibleNullReferenceException
XElement element = xDocument.Root.Element("group");
...
// ReSharper restore PossibleNullReferenceException


[1] https://jetbrains.com/help/resharper/Reference__Code_Inspections_CSHARP.html
[2] https://editorconfig.org/
Глаза у меня добрые, но рубашка — смирительная!
Re[3]: Possible NullReferenceException...
От: Ночной Смотрящий Россия  
Дата: 16.07.21 08:34
Оценка: 16 (1) +3
Здравствуйте, Shmj, Вы писали:

S>>>Согласно протоколу элемент в документе обязательно существует

НС>>Какому протоколу?
S>Согласно протоколу обмена, т.е. соглашениям с тем, кто этот XML-документ предоставляет.

И? Проверять то на соответствие кто должен?

S>Так там внутри запроса этих проверок с десяток будет. Зачем дублировать код?


Передавай не документ, а рутовый элемент, тогда проверка уедет наверх.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[3]: <Nullable>enable</Nullable>
От: Ночной Смотрящий Россия  
Дата: 16.07.21 08:35
Оценка:
Здравствуйте, Shmj, Вы писали:

S>А если внутри запроса те же варнинги с десяток? Там же не только Root но и .Element("group") может быть null.


https://github.com/rsdn/CodeJam/blob/master/CodeJam.Main/Xml/XNodeExtensions.cs
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[3]: Possible NullReferenceException...
От: Mystic Artifact  
Дата: 17.07.21 00:48
Оценка: 79 (2)
Здравствуйте, Shmj, Вы писали:

S>Согласно протоколу обмена, т.е. соглашениям с тем, кто этот XML-документ предоставляет.

Протокол обмена является конвенцией (договоренностью) между клиентом и условным сервером, которая предъявлет некоторые требования к обоим.

Он гласит, что клиент может рассчитывать, на то, что сервер ему пришлет данные, которые соответствуют протоколу.
Сервер в свою очередь ожидает от клиента, данные, соответствующие протоколу.
Может/ожидает в моей фразировке означают, мягкую форму обязанности. В RFC — это называется SHOULD. Почему так? Потому что — обещал — не значит женился. А вот когда обязан — это MUST. Так вот — в этом случае — речь исключительно о обещаниях. Безусловно, нужно понимать, кто и с кем разговаривает по протоколу. Если это софт который разговаривает сам с собой в одном процессе или на одном хосте но с одного бинарника — будет нелепым ожидать ересь, и всё равно стоит хотя бы минимально защититься.

Это подразумевает само собою вполе себе простую импликацию — если это обязательный элемент (например корневой элемент документа, правильно названный, с правильным нэймспейсом) => то ты его имеешь право принять. Однако, если этот элемент имеет другое имя, эта же договорённость обязывает (чаще всего) — не принять такой документ. В твоём приведенном коде (весь не видно) — не видно проверки что это у нас вообще за документ, и больше похоже на игнорирование корневого элемента.

Более того, в реальном мире, обе стороны совершенно не могут принять на веру то, что документ правильно сформирован. На то есть масса причин: от банальных сетевых сбоев (космических сбоев с искажением данных, которые вроде бы как не возможны, но всё таки если такое видел хоть раз в жизни — то понимаешь, что и такое может быть), до банальных логических ошибок. Ведь клиент пишет человек, в том числе даже, если ты сам, софт другой версии и т.п. Ну и вообще если протокол неправильно используется.

Про XML (да и не только) — была и есть старая атака основанная на эксплуатации хэш-таблиц в не особо поворотливых реализациях (посылается огромный документ который кто-нибудь наивно скормит XML парсеру, и выйдет так, что внезапно весь миллион элементов имеют один и тот же хэш => что серьезно влияет на дальнейшие действия в тех или иных реализациях, в частности в хэш-таблицах с разрешением коллизий через цепочки — это проблема. А для открытой адресации... такой проблемы нет. Но проблемы всё равно будут, если подобрать правильные значения.). XmlDocument — в этом смысле как раз таки не подвержен таким атакам, т.к. хеширование разбавляется солью. А XDocument зависит на глобальные XNamespace/XName — и будь они трижды lock-free — они всё таки просто хэш-таблицы и таким образом очень даже подвержены к атакам "мусором".

А противостоят этому всему и сразу — нормальные парсеры (десериализаторы) которые, учитывают схему документа, которые заранее осведомлены о возможной структуре документа, и на неправильную структуру либо ругаются сразу, либо, в соответствии с конвенцией, если таковые существуют — игнорируют неизвестные поля, или наоборот используют зачение первого или последнего поля. (В мире существуют вариации на любой лад.)

И после этого — мы должны заиметь удобный объект, вдобавок который предварительно провалидирован хотя бы на предвариельную похожесть документа. И в реалиях дотнета — это почти наверняка лучше, чем сначала разложить входные байты в узлы дерева (XNode), потом это разложить в объекты и т.п.

Но, мне так думается — что, в твоем случае, как уже советовали выше — в шарпе стоит поставить знак "!" — ведь он решает все проблемы, варнинги не сыпятся...
Re[4]: Randomization
От: Qbit86 Кипр
Дата: 17.07.21 09:50
Оценка:
Здравствуйте, Mystic Artifact, Вы писали:

MA>А противостоят этому всему и сразу — нормальные парсеры (десериализаторы)


В случае строковых ключей этому противостоит ещё и рандомизация в стандартных компараторах.
Глаза у меня добрые, но рубашка — смирительная!
Re[5]: Randomization
От: Mystic Artifact  
Дата: 20.07.21 16:48
Оценка:
Здравствуйте, Qbit86, Вы писали:

MA>>А противостоят этому всему и сразу — нормальные парсеры (десериализаторы)

Q>В случае строковых ключей этому противостоит ещё и рандомизация в стандартных компараторах.
Я абсолютно согласен, и так (по крайней мере был) устроен XmlDocument. XName/XNamespace — (вроде?) не имеют даже рандомизации на уровне процесса (в угоду серилазиации может быть, я не знаю).
Так или иначе это лишь один из способов борьбы с мусором, и во многом больше похож на борьбу с последствиями... Мне кажется если к документу можно примерить простую схему в потоковом режиме (не все фичи схемы одинаково полезны) / обеспечить лимитами, то и рандомизация не понадобится. Хотя в данном случае ключевое слово "мне кажется", т.к. как обычно — находится такой кейс о котором мы даже не мечтали.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.