Re[2]: { }
От: syrompe  
Дата: 26.10.23 21:20
Оценка: 5 (1) +2 -1 :)))
G>Если свойства не указаны, то трактуется также, как is not null

Ох уж это новый дивный мир си шарпа.
Я помнится похихикивал над несуразными примерами JavaScript'а, а теперь как-то неловко...

1. Сначала мы дружно писали
if(a!=null)

и спали спокойно
2. Потом нам завезли Nullable и местами пришлось писать
if(a.HasValue)

3. Потом завезли null propagation и стали появляться
if(a?.b?.HasValue==true)

4. Потом появились недоделанные паттерны
if(a is not null)

причем на некоторых проектах в codestyle прям жестко прописано что на null только через is проверять ибо оператор == злобный буратино переопределить может.
5. Теперь вот еще Property pattern'ы
if(a is {b: not null})

правда тут сюрприз бывает
Re[2]: Declaration
От: Qbit86 Кипр
Дата: 26.10.23 19:34
Оценка: 6 (1) +4
Здравствуйте, gandjustas, Вы писали:

G>Конечно за такой код надо бить по рукам.


Нет, за такой код бить по рукам не надо, это вполне легитимный способ, рекомендуемый анализаторами Roslyn или Rider.

G>Если свойства не указаны, то трактуется также, как is not null


Нет, is { } не эквивалентен is not null, потому что is not null не вводит имя переменной. Ты не можешь написать
if (stage() is not null stages)
    stages.SomeMethod();
Глаза у меня добрые, но рубашка — смирительная!
Re[8]: Отличать
От: Qbit86 Кипр
Дата: 30.10.23 06:44
Оценка: 93 (3) +1
Здравствуйте, Sinclair, Вы писали:

S>На первый взгляд да. А в каких сценариях требуется отличать null-ссылку от ссылки на разрушенный объект, который уже удалён из дерева сцены?


Например, null-ссылка может быть признаком того, что её не проинициализировали — не привязали в Редакторе перетаскиванием одного игрового объекта в поле на другом объекте. Такую ситуацию надо обрабатывать иначе, чем просто ссылку на разрушенный объект. Anyway, атомарным кирпичиком должен быть IsDisposed(), из которого можно при необходимости собрать статический метод (расширения) IsNullReferenceOrDisposed(). А не наоборот, когда у тебя цепочка if (go is null) { … } else if (go == null) { … }, причём внутри второй проверке ещё раз повторно происходит и первая (ссылочное сравнение на null).

Сопряжённым источником фрустрации для многих разработчиков Unity (они в основном не специалисты в языке) было появление в очередной версии Unity поддержки null propagation и null coalescing в синтаксисе C#. Раньше они не задумывались, какой механизм лежит за тем, что их ссылки как бы «обнуляются» при смерти объекта. Многим казалось, что это такая магия рантайма (а не языка — переопределение оператора). И когда они стали заменять проверки if (go != null) go.Foo() на новый модный null propagation go?.Foo(), получали изменение семантики и неожиданный NullReferenceException (вместо хотя бы ObjectDisposedException).
Глаза у меня добрые, но рубашка — смирительная!
Отредактировано 30.10.2023 6:46 Qbit86 . Предыдущая версия .
Re[6]: `operator ==` в Unity
От: Qbit86 Кипр
Дата: 29.10.23 06:40
Оценка: 19 (2) :))
Здравствуйте, Sinclair, Вы писали:

S>Ведь если оператор сравнения перегружен каким-то нехорошим образом так, что он неверно проверяет на null, то у проекта проблемы тут не в code style. И при помощи is эти проблемы не решить.

S>Что не так с operator== в Unity?

У игровых объектов (или компонентов на них висящих) может быть статус «разрушен» — когда они удалены из дерева сцены, их ресусрсы освобождены, они не могут получать событий обновления, etc.
Так вот, вместо того, чтобы добавить в API свойство или метод IsAlive или IsDisposed, расработчики Unity переопределили operator ==, изменив его логику для случая сравнения с null. Проверка вида if (myGameObject == null) возвращает true не только когда ссылка is null, но и если объект разрушен; причём другого способа проверить разрушенность нет.
А если ты вызываешь методы движка на разрушенном объекте (имея на него ненулевую ссылку), то разработчики выбрасывают исключение типа NullReferenceException.

Абсолютно проклято.
Глаза у меня добрые, но рубашка — смирительная!
Отредактировано 29.10.2023 6:56 Qbit86 . Предыдущая версия . Еще …
Отредактировано 29.10.2023 6:53 Qbit86 . Предыдущая версия .
Re[4]: { }
От: vmpire Россия  
Дата: 27.10.23 17:08
Оценка: +2 -1 :)
Здравствуйте, gandjustas, Вы писали:

G>В С# ситуация другая — там появляется много языковых фич, которые программисты не успевают изучать. Но все эти выражения помогают писать код гораздо более компактно, чем без них.


G>Например: проверка схемы данных в JSON (нерегулярной структуры). Два поля, если присутствуют в любом элементе, то должны быть согласованы, одно из них — строковый идентификатор объекта, второе — этого же объекта из трех частей (проект, модуль, имя) в виде пути на сайте

G>
G>            if (obj.TryGetPropertyValue("entity", out var entityNode) &&
G>                obj.TryGetPropertyValue("dataPath", out var dataPathNode) &&
G>                entityNode is JsonValue entityValue &&
G>                dataPathNode is JsonValue dataPathValue &&
G>                entityValue.TryGetValue<string>(out var entityId) &&
G>                dataPathValue.TryGetValue<string>(out var dataPath))
G>            {
G>            }
G>


G>Написать то же самое без PM и out var займет в разы дольше.

Только вот когда в разы дольше, тогда можно дописать нормальную диагностику ошибки с сообщением, на каком элементе упал парсинг. А в приведённом примере единственное что можно написать, это
            else
            {
              throw new Exception("Что-то пошло не так");
            }

Так что это палка о двух концах.
Re[3]: { }
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.10.23 14:03
Оценка: 20 (2) +1
Здравствуйте, syrompe, Вы писали:

G>>Если свойства не указаны, то трактуется также, как is not null


S>Ох уж это новый дивный мир си шарпа.

S>Я помнится похихикивал над несуразными примерами JavaScript'а, а теперь как-то неловко...
Отличная шутка, коллега! Я тоже посмеялся.

S>1. Сначала мы дружно писали

S>
S>if(a!=null)
S>

S> и спали спокойно
S>2. Потом нам завезли Nullable и местами пришлось писать
S>
S>if(a.HasValue)
S>

Хм. А в каком это контексте пришлось?
Чем вас не устроило продолжать писать if(a!=null)?

S>3. Потом завезли null propagation и стали появляться

S>
S>if(a?.b?.HasValue==true)
S>

Опять же — если вас категорически не устраивает возможность писать if(a?.b != null), то вы можете продолжать пользоваться старым добрым if(a != null && a.b != null).
Возможность писать if (((а == null) == false).ToString() == "true") была доступна сразу в C# 1.0, тут за десять мажорных релизов не изменилось ровным счётом ничего.

S>4. Потом появились недоделанные паттерны

S>
S>if(a is not null)
S>

Это просто такой corner case на пересечении нескольких фич, каждая из которых была спроектирована для своей цели.
Но язык должен позволять комбинировать фичи не только конкретным способом, но и любым легальным.
Вы же заметили, что теперь можно писать не только if (a == 42), но и if(a is 42)?
Над этим можно было бы похихикать, если бы не один нюанс: набор разрешённых компайл-тайм типов a в этих случаях отличается.
В частности:
bool CheckFor42(object a)
{
  return a == 42; // fail
  return a is 42;  // fine
}

Так что второй вариант безо всякого юмора гораздо удобнее, чем дедовский
  return a is int && (a as int) == 42;

Ну, а возможность таким же образом сравнивать с null — побочный эффект, не запрещать же такую запись только от того, что константа null совместима с любым reference или nullable типом.

S>причем на некоторых проектах в codestyle прям жестко прописано что на null только через is проверять ибо оператор == злобный буратино переопределить может.

Ну так и замечательно, в чём проблема?
В том, что вам нестерпимо хотелось писать if (!object.ReferenceEquals(a, null)), а вам злые дяди запрещают?
Ведь если оператор сравнения перегружен каким-то нехорошим образом так, что он неверно проверяет на null, то у проекта проблемы тут не в code style. И при помощи is эти проблемы не решить.

S>5. Теперь вот еще Property pattern'ы

S>
S>if(a is {b: not null}) 
S>

S>правда тут сюрприз бывает
Даже интересно стало, какой сюрприз. Ну, и, собственно, что заставляет вас писать именно так, если вам по-прежнему хочется if(a != null && a.b != null).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Declaration
От: Петрухин Эдуард Россия  
Дата: 27.10.23 06:12
Оценка: 11 (2) +1
Здравствуйте, Qbit86, Вы писали:

Q>Здравствуйте, gandjustas, Вы писали:


G>>Конечно за такой код надо бить по рукам.


Q>Нет, за такой код бить по рукам не надо, это вполне легитимный способ, рекомендуемый анализаторами Roslyn или Rider.


G>>Если свойства не указаны, то трактуется также, как is not null


Q>Нет, is { } не эквивалентен is not null, потому что is not null не вводит имя переменной. Ты не можешь написать

Q>
if (stage() is not null stages)
Q>    stages.SomeMethod();
Q>

Имя переменной можно отдельно ввести:
if (stage() is not null and var stages)
    stages.SomeMethod();

... но есть ньюанс с nullable value типами:
https://twitter.com/controlflow/status/1625933876018221069
https://sharplab.io/#v2:EYLgtghglgdgNAFxAJwK4wD4AEBMBGAWAChiA3CZAAgHtgArSgXkpgFMB3Sgb0oCFqAHk0oAKWAgD8ASkoAWHJQC+AbmLEoAM1G0GUAM7c+gkC2oIWqADaXKEGABNK5KgjxKZAZQAW1dgBUATwAHVhFXKVUiTW16Sn1DfgETSkNFFJS7R2dKBAVFTx9/YNDciLUiLFlKb19AkIAePwA+ET8cmUYmyiw8AE4w4uoNVqkIoA==
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[3]: { }
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 27.10.23 11:46
Оценка: 84 (2)
Здравствуйте, syrompe, Вы писали:

G>>Если свойства не указаны, то трактуется также, как is not null


S>Ох уж это новый дивный мир си шарпа.

S>Я помнится похихикивал над несуразными примерами JavaScript'а, а теперь как-то неловко...
Несуразица JS связана с его динамической типизацией. Много способов написать корректный код, который работает совсем не так как ожидаешь

В С# ситуация другая — там появляется много языковых фич, которые программисты не успевают изучать. Но все эти выражения помогают писать код гораздо более компактно, чем без них.

Например: проверка схемы данных в JSON (нерегулярной структуры). Два поля, если присутствуют в любом элементе, то должны быть согласованы, одно из них — строковый идентификатор объекта, второе — этого же объекта из трех частей (проект, модуль, имя) в виде пути на сайте
void ProcessContent(JsonNode node)
{
    switch (node)
    {
        case JsonObject obj:
            if (obj.TryGetPropertyValue("entity", out var entityNode) &&
                obj.TryGetPropertyValue("dataPath", out var dataPathNode) &&
                entityNode is JsonValue entityValue &&
                dataPathNode is JsonValue dataPathValue &&
                entityValue.TryGetValue<string>(out var entityId) &&
                dataPathValue.TryGetValue<string>(out var dataPath))
            {
                if (dataPath.Split("/") is
                    ["api", "v1.0", "dynamicEntityTable", var projectName, var moduleName, var name])
                {
                    // ....
                }
                else
                {
                    // ....
                }
            }
            foreach (var pair in obj)
            {
                await ProcessContent(pair.Value);
            }

            break;
        case JsonArray arr:
            foreach (var subNode in arr)
            {
                await ProcessContent(subNode);
            }

            break;
    }
}


Написать то же самое без PM и out var займет в разы дольше.
Re[4]: `is` vs. `==`
От: Qbit86 Кипр
Дата: 27.10.23 15:31
Оценка: 80 (1) +1
Здравствуйте, Sinclair, Вы писали:

S>Вы же заметили, что теперь можно писать не только if (a == 42), но и if(a is 42)?

S>Над этим можно было бы похихикать, если бы не один нюанс: набор разрешённых компайл-тайм типов a в этих случаях отличается.

Разница ещё и в том, что паттерн, с которым значение сравнивается через is, должен быть коснтантой; часто это enum. То есть is более точная и строгая форма записи, чем ==. Я предпочитаю is, когда сравниваю с константой.

S>Ведь если оператор сравнения перегружен каким-то нехорошим образом так, что он неверно проверяет на null, то у проекта проблемы тут не в code style.


А вот сейчас было больно; я работаю с Unity :(
Глаза у меня добрые, но рубашка — смирительная!
Re: { }
От: _FRED_ Черногория
Дата: 27.10.23 15:30
Оценка: +2
Здравствуйте, BlackEric, Вы писали:

BE>Я сейчас глупость спрошу, но зачем в коде

BE>if (stage() is { } stages)

BE>{ }, что они означают?
BE>stage возвращает List<Stage>. Stages имеет этот же тип.

Я извиняюсь, что с непрошенными советами лезу, не стесняйтель заминусить.

Но кажется не очень удобной идея возврата null вместо List<Stage> (Guidelines for Collections / Collection Properties and Return Values):

❌ DO NOT return null values from collection properties or from methods returning collections. Return an empty collection or an empty array instead.

The general rule is that null and empty (0 item) collections or arrays should be treated the same.

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

Если вы возвращаете null чтобы не создавать лишний раз пустой список (когда он не нужен), то тут лучше изменить тип возвращаемого значения на, например, массив или ридонли интерфейс (от IEnumerable<> до IReadOnlyList<>) и возвращать Array.Empty<Stage>(); вметсо нулла. а пользователь уже, если и когда ему будет нужно, сможет скопировать полученную коллекцию в List<Stage>. Если такое лишнее копирование не устраивает, то нужна будет своя реализация, например, IReadOnlyList<> с методом ToList() которая для пустой "внутренней" коллекции создаст новый List<>, а для уже готового List<> его и вернёт.
Help will always be given at Hogwarts to those who ask for it.
Re: { }
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 26.10.23 16:22
Оценка: 6 (1)
Здравствуйте, BlackEric, Вы писали:

BE>Я сейчас глупость спрошу, но зачем в коде


BE>
BE>if (stage() is { } stages)
BE>

BE>{ }, что они означают?


BE>stage возвращает List<Stage>. Stages имеет этот же тип.



Это Property pattern. Внутри него можно указать свойства объекта и паттерны для них, например так:
if (stage() is { Count: > 0 } stages)


Если свойства не указаны, то трактуется также, как is not null

Конечно за такой код надо бить по рукам.
Re: { }
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.10.23 16:31
Оценка: 6 (1)
Здравствуйте, BlackEric, Вы писали:

BE>Я сейчас глупость спрошу, но зачем в коде


BE>
BE>if (stage() is { } stages)
BE>

BE>{ }, что они означают?
Это — property pattern с пустым списком пропертей.
Эквивалентно проверке на not null:

To check if the string s is non-null, you can write any of the following forms

if (s is object o) ... // o is of type object
if (s is string x) ... // x is of type string
if (s is {} x) ... // x is of type string
if (s is {}) ...

BE>stage возвращает List<Stage>. Stages имеет этот же тип.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Отредактировано 27.10.2023 1:34 Sinclair . Предыдущая версия .
Re[5]: { }
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 27.10.23 11:14
Оценка: +1
Здравствуйте, syrompe, Вы писали:

S>>Все, что ниже поскипано не относится к несуразностям. Просто стало больше возможностей, для более краткого и выразительного написания кода.

S>Ну скажем 6 способов проверить на нулл и каждый со своими ньюансами все же не есть хорошо.
Почему? Если способы хорошие, то пусть работает. Если способы плохие, то компилятор может проверять это. И в случае C# — проверяет.
{ }
От: BlackEric http://black-eric.lj.ru
Дата: 26.10.23 15:57
Оценка:
Я сейчас глупость спрошу, но зачем в коде

if (stage() is { } stages)

{ }, что они означают?

stage возвращает List<Stage>. Stages имеет этот же тип.
https://github.com/BlackEric001
Re: { }
От: Разраб  
Дата: 27.10.23 02:06
Оценка:
Здравствуйте, BlackEric, Вы писали:

BE>Я сейчас глупость спрошу, но зачем в коде


BE>
BE>if (stage() is { } stages)
BE>

BE>{ }, что они означают?

Кто ж его знает. может ссылочный тип?
ЯП со сложным синтаксисом склонны к деградации, например F#
let xs = [1;2;3]
(* было *)
let x = xs.[0] // => 1
(* стало *)
let x = xs[0] // => 1
let x = xs [0] // =>  error FS3217: Это значение не является функцией, и применить его невозможно. Вы хотели обратиться к индексатору с помощью "xs[index]"?

иногда нужно остановится. например как сделали в схеме. просто сказали скобочек достаточно.
При это интересно следующее (это же тот же дотнет):
> let xs:List<Stage> = null;;
val xs : List<Stage> = null

> let r = match xs with | :? List<Stage> as x -> x.GetType().ToString() | _ -> "noname";;

  let r = match xs with | :? List<Stage> as x -> x.GetType().ToString() | _ -> "noname";;
  ------------------------^^^^^^^^^^^^^^

stdin(15,25): warning FS0067: Данная проверка типа или понижение будет всегда сохраняться

val r : string = "noname"

не пошел в первую ветку, хотя тип был жеско задан.

Может быть кондишины должны оставаться простыми? типа true/(false or nil).
А уже для специализации использовать полиморфизм?
Было же прекрасно в C# 1
https://rsdn.org/article/dotnet/asis.xml
Автор(ы): Владислав Чистяков (VladD2)
Дата: 18.12.2004
Работая над открытыми проектами, автор заметил, что операторы as и is многими программистами зачастую используются ненадлежащим образом. Результатом очередного двухчасового поиска ошибки и стала эта статья.


☭ ✊ В мире нет ничего, кроме движущейся материи.
Отредактировано 27.10.2023 2:18 Разраб . Предыдущая версия .
Re[3]: { }
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 27.10.23 09:09
Оценка:
Здравствуйте, syrompe, Вы писали:

G>>Если свойства не указаны, то трактуется также, как is not null


S>Ох уж это новый дивный мир си шарпа.

S>Я помнится похихикивал над несуразными примерами JavaScript'а, а теперь как-то неловко...

Все, что ниже поскипано не относится к несуразностям. Просто стало больше возможностей, для более краткого и выразительного написания кода.
А с непривычки на Linq все плевались. Для них это было огромной несуразностью.
А вот в JS 1+"2" это несуразность
и солнце б утром не вставало, когда бы не было меня
Re[4]: { }
От: syrompe  
Дата: 27.10.23 10:04
Оценка:
S>Все, что ниже поскипано не относится к несуразностям. Просто стало больше возможностей, для более краткого и выразительного написания кода.
Ну скажем 6 способов проверить на нулл и каждый со своими ньюансами все же не есть хорошо.

S>А с непривычки на Linq все плевались. Для них это было огромной несуразностью.

Я вот до сих пор плююсь, но тут дело вкуса. С момента его появления у меня сменилось 3 проекта и нигде он не приветствовался (местами даже явным запретом в codestyle)

S>А вот в JS 1+"2" это несуразность

Тут да до JS еще очень далеко, но тенденция напрягает немного.
Re[5]: { }
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 27.10.23 11:12
Оценка:
Здравствуйте, syrompe, Вы писали:

S>>Все, что ниже поскипано не относится к несуразностям. Просто стало больше возможностей, для более краткого и выразительного написания кода.

S>Ну скажем 6 способов проверить на нулл и каждый со своими ньюансами все же не есть хорошо.

S>>А с непривычки на Linq все плевались. Для них это было огромной несуразностью.

S>Я вот до сих пор плююсь, но тут дело вкуса. С момента его появления у меня сменилось 3 проекта и нигде он не приветствовался (местами даже явным запретом в codestyle)

Я вот сейчас с ODATA работаю, и на Linq очень удобно REST запросы генерить Linq to ODATA
Я не говорю про DB и прочие коллекции
S>>А вот в JS 1+"2" это несуразность
S>Тут да до JS еще очень далеко, но тенденция напрягает немного.

Тенденция прежде всего из-за ПМ. К нему надо привыкнуть. Но значительно выразительнее.
и солнце б утром не вставало, когда бы не было меня
Re[3]: Declaration
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 27.10.23 11:30
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Нет, is { } не эквивалентен is not null, потому что is not null не вводит имя переменной. Ты не можешь написать

Q>
if (stage() is not null stages)
Q>    stages.SomeMethod();
Q>


про var уже ответили. Еще можно
https://learn.microsoft.com/ru-ru/dotnet/csharp/language-reference/operators/patterns#parenthesized-pattern
if (input is not (float or double))
{
    return;
}
и солнце б утром не вставало, когда бы не было меня
Re[4]: { }
От: _FRED_ Черногория
Дата: 27.10.23 15:16
Оценка:
Здравствуйте, gandjustas, Вы писали:

G> entityValue.TryGetValue<string>(out var entityId) &&
G> dataPathValue.TryGetValue<string>(out var dataPath))

Прошу прощенгия, а почему не так:
entityValue.TryGetValue(out string entityId) &&
dataPathValue.TryGetValue(out string dataPath))

?
Help will always be given at Hogwarts to those who ask for it.
Re[5]: { }
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 27.10.23 15:32
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, gandjustas, Вы писали:


_FR>Прошу прощенгия, а почему не так:

_FR>
_FR>entityValue.TryGetValue(out string entityId) &&
_FR>dataPathValue.TryGetValue(out string dataPath))
_FR>

_FR>?

Не знаю, видимо из примера скопипастили изначально.
Re[2]: Populate()
От: Qbit86 Кипр
Дата: 27.10.23 15:37
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Если такое лишнее копирование не устраивает, то нужна будет своя реализация, например, IReadOnlyList<> с методом ToList() которая для пустой "внутренней" коллекции создаст новый List<>, а для уже готового List<> его и вернёт.


Или вместо возврата колекции предоставить метод Populate<TCollection>(TCollection collection) where TCollection..., который заполняет уже существующую коллекцию (которую аллоцирует и предоставляет вызывающая сторона).
Глаза у меня добрые, но рубашка — смирительная!
Re[3]: Populate()
От: _FRED_ Черногория
Дата: 27.10.23 17:04
Оценка:
Здравствуйте, Qbit86, Вы писали:

_FR>>Если такое лишнее копирование не устраивает, то нужна будет своя реализация, например, IReadOnlyList<> с методом ToList() которая для пустой "внутренней" коллекции создаст новый List<>, а для уже готового List<> его и вернёт.


Q>Или вместо возврата колекции предоставить метод Populate<TCollection>(TCollection collection) where TCollection..., который заполняет уже существующую коллекцию (которую аллоцирует и предоставляет вызывающая сторона).


Так цимес вроде именно в том, что вызывающей стороне не известно количество элементов и лишних аллокаций на пустые коллекции хочется как раз избежать.

P.S. С [tt] классно
Help will always be given at Hogwarts to those who ask for it.
Re[4]: GetByteCount()
От: Qbit86 Кипр
Дата: 27.10.23 17:15
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Так цимес вроде именно в том, что вызывающей стороне не известно количество элементов и лишних аллокаций на пустые коллекции хочется как раз избежать.


Так чтобы это количество стало известно, в современных API в BCL добавляют методы вроде GetByteCount() или GetMaxEncodedToUtf8Length(). Обычно в сценариях работы со span'ами, но и в обычных можно. Общая идея: не брать на себя аллокацию, пусть вызывающая сторона выделяет или берёт из пула.

_FR>P.S. С [tt] классно


А был бы Markdown, ещё лучше было бы!
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: { }
От: BlackEric http://black-eric.lj.ru
Дата: 27.10.23 18:58
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Но кажется не очень удобной идея возврата null вместо List<Stage> (Guidelines for Collections / Collection Properties and Return Values):

_FR>

_FR>❌ DO NOT return null values from collection properties or from methods returning collections. Return an empty collection or an empty array instead.

_FR>The general rule is that null and empty (0 item) collections or arrays should be treated the same.

_FR>Потому как раз, что пользователю такого свойства или метода неудобно делать проверки на нулл, проще проверить, пуста ли коллекция.

_FR>Если вы возвращаете null чтобы не создавать лишний раз пустой список (когда он не нужен), то тут лучше изменить тип возвращаемого значения на, например, массив или ридонли интерфейс (от IEnumerable<> до IReadOnlyList<>) и возвращать Array.Empty<Stage>(); вметсо нулла. а пользователь уже, если и когда ему будет нужно, сможет скопировать полученную коллекцию в List<Stage>. Если такое лишнее копирование не устраивает, то нужна будет своя реализация, например, IReadOnlyList<> с методом ToList() которая для пустой "внутренней" коллекции создаст новый List<>, а для уже готового List<> его и вернёт.


У нас так часто в проекте. Возвращается null или пустой список или заполненный. Null как правило, если документ только создается.
https://github.com/BlackEric001
Re[5]: { }
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 27.10.23 19:51
Оценка:
Здравствуйте, vmpire, Вы писали:

V>Только вот когда в разы дольше, тогда можно дописать нормальную диагностику ошибки с сообщением, на каком элементе упал парсинг.

Во-первых это Exception-free код, там никаких путей исполнения через эксепшены нет. Если что-то падает, то никто не перехватывает.
Во-вторых текущий проверяемый JsonObject доступен в том числе для репортинга.

V>А в приведённом примере единственное что можно написать, это

V>
V>            else
V>            {
V>              throw new Exception("Что-то пошло не так");
V>            }
V>

Ты удивишься, но в реальном коде как раз возвращается в каком элементе возникает ошибка.

V>Так что это палка о двух концах.

Конечно нет, просто кривизна рук разная.
Re[2]: { }
От: Разраб  
Дата: 28.10.23 00:22
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>❌ DO NOT return null values from collection properties or from methods returning collections. Return an empty collection or an empty array instead.


Логика требует, очевидно. 0 — ничего нет или не получилось?
null — как индикатор что что-то пошло нет так, или кидать исключение,
в любом случае придется как-то обработать 3-й вариант.
иначе получаем скрытую ошибку в программе.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[4]: { }
От: Разраб  
Дата: 28.10.23 00:44
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>
G>void ProcessContent(JsonNode node)
G>{
G>    switch (node)
G>    {
G>        case JsonObject obj:
G>


G>Написать то же самое без PM и out var займет в разы дольше.

А не проще:
 case JsonObject obj:
    var x = obj.Deserialize<Option?>();
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[5]: `is` vs. `==`
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.10.23 05:11
Оценка:
Здравствуйте, Qbit86, Вы писали:
Q>А вот сейчас было больно; я работаю с Unity
Не знаком с подробностями. Что не так с operator== в Unity?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: { }
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.10.23 06:16
Оценка:
Здравствуйте, Разраб, Вы писали:

G>>Написать то же самое без PM и out var займет в разы дольше.

Р>А не проще:
Р>
Р> case JsonObject obj:
Р>    var x = obj.Deserialize<Option?>();
Р>


Не знаю, а пример код с той же семантикой какой будет?
Re[7]: `operator ==` в Unity
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.10.23 02:04
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>У игровых объектов (или компонентов на них висящих) может быть статус «разрушен» — когда они удалены из дерева сцены, их ресусрсы освобождены, они не могут получать событий обновления, etc.

Q>Так вот, вместо того, чтобы добавить в API свойство или метод IsAlive или IsDisposed, расработчики Unity переопределили operator ==, изменив его логику для случая сравнения с null. Проверка вида if (myGameObject == null) возвращает true не только когда ссылка is null, но и если объект разрушен; причём другого способа проверить разрушенность нет.
Q>А если ты вызываешь методы движка на разрушенном объекте (имея на него ненулевую ссылку), то разработчики выбрасывают исключение типа NullReferenceException.

Q>Абсолютно проклято.
На первый взгляд да. А в каких сценариях требуется отличать null-ссылку от ссылки на разрушенный объект, который уже удалён из дерева сцены?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.