Re: C# 8 и null-допустимость - ошибка на миллиард
От: vmpire Россия  
Дата: 12.05.20 19:10
Оценка: 22 (2) +9 -3
Здравствуйте, Shmj, Вы писали:

S>https://m.habr.com/ru/company/piter/blog/501520/


S>Пишут что сглупили, теперь хотят все исправить. Ваше мнение?

Я считаю, что самая большая ошибка в борьбе с NRE — это борьба с NRE.
Если заменить null на какое-нибудь значение, которое будет тихо пропускаться при обработке, то станет ещё хуже: ошибка никуда не денется, но вместо явного падения будет выдаваться неправильный результат где-то совсем в другом месте и отследить будет на порядок сложнее.
Ведь чтобы избежать ошибок компиляции 90% разработчиков просто понавтыкают при объявлении переменной инициализацию в пустую строку.

Да, часть таких ошибок отловит компилятор, но весьма малую часть. А отлов остальных значительно усложнится, и получится ещё более дорогая проблема.
Похожая ситуация была в джаве с явным объявлением exceptions. Насколько я смотрел в джавовский код, никто эти не пользуется, так как в мало-мальски сложной програме отследить это всё равно невозможно.
Точно также и с null — мало кто будет пользоваться новыми возможностями и основная проблема не пофиксится, но добавится новая
Re[2]: C# 8 и null-допустимость - ошибка на миллиард
От: Sinclair Россия https://github.com/evilguest/
Дата: 13.05.20 11:26
Оценка: +5
Здравствуйте, vmpire, Вы писали:

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


S>>https://m.habr.com/ru/company/piter/blog/501520/


S>>Пишут что сглупили, теперь хотят все исправить. Ваше мнение?

V>Я считаю, что самая большая ошибка в борьбе с NRE — это борьба с NRE.
V>Если заменить null на какое-нибудь значение, которое будет тихо пропускаться при обработке, то станет ещё хуже: ошибка никуда не денется, но вместо явного падения будет выдаваться неправильный результат где-то совсем в другом месте и отследить будет на порядок сложнее.
Ну, фича вроде бы не про замену null на какое-нибудь значение. А про чёткий контроль контрактов: т.н. "явное падение" очень часто происходит тогда, когда по колл стеку уже ничего не разберёшь.
Ну вот обратились мы к полю ._xx, а оно — null. Почему оно null — да х.з. Надо разматывать назад не только стек, а всю предысторию — откуда, что, куда.
Это дорого и трудно. Куда лучше, если об этом нам скажет компилятор и заранее. Тогда у нас будет возможность обложить все места, откуда в наш ._хх может приехать null, явными проверками с throw ArgumentNullException.
V>Ведь чтобы избежать ошибок компиляции 90% разработчиков просто понавтыкают при объявлении переменной инициализацию в пустую строку.
Ну, не всякую переменную можно инициализировать пустой строкой.

V>Похожая ситуация была в джаве с явным объявлением exceptions. Насколько я смотрел в джавовский код, никто эти не пользуется, так как в мало-мальски сложной програме отследить это всё равно невозможно.

V>Точно также и с null — мало кто будет пользоваться новыми возможностями и основная проблема не пофиксится, но добавится новая
Посмотрим. Пока что у первых ласточек отзывы восторженные.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: C# 8 и null-допустимость - ошибка на миллиард
От: hi_octane Беларусь  
Дата: 12.05.20 23:51
Оценка: +2 -1 :)
V>Ведь чтобы избежать ошибок компиляции 90% разработчиков просто понавтыкают при объявлении переменной инициализацию в пустую строку.
И это не завернут на code-review.

V>Точно также и с null — мало кто будет пользоваться новыми возможностями и основная проблема не пофиксится, но добавится новая

Х-з. Я просто включил в проекте эту нуллабельность, вылетело несколько тыщ варнингов, за пару недель работы над другими фичами число припало до нескольких сотен. Через месяц поставил warning as error, и полечили. Х-з помогло оно от реальных ошибок или нет — покрытие тестами было хорошее, но ощущение что догадываешься что все объекты у тебя инициализированы надёжно и их можно не проверять, вполне приятное.
Re[3]: C# 8 и null-допустимость - ошибка на миллиард
От: · Великобритания  
Дата: 13.05.20 13:44
Оценка: 5 (1) +1
Здравствуйте, Sinclair, Вы писали:

S>Ну вот обратились мы к полю ._xx, а оно — null. Почему оно null — да х.з. Надо разматывать назад не только стек, а всю предысторию — откуда, что, куда.

Какое-то плохое объяснение... Чем это принципиально отличается от:
Ну вот обратились мы к полю ._xx, а оно — "". Почему оно "" — да х.з. Где вместо "" может быть [], 0 и т.д.

По-моему основная проблема, что null насильно добавляет ещё одно значение в область значений всех типов которое в подавляющем большинстве случаев не нужно, но заставляет явно об этом помнить каждый раз, усложняет код часто бессмысленными проверками и/или грозит падением. Притом, если скажем int/string/etc можно обернуть в класс и заставить его быть только в определённом диапазоне, то с null такой трюк не пройдёт, выразить кодом, что null тут нет или есть — не получится.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: C# 8 и null-допустимость - ошибка на миллиард
От: Kolesiki  
Дата: 14.05.20 14:01
Оценка: +1 :)
Здравствуйте, Shmj, Вы писали:

S>Пишут что сглупили, теперь хотят все исправить. Ваше мнение?


Кто именно сглупил и что исправляют??
Re: C# 8 и null-допустимость - ошибка на миллиард
От: Aquilaware  
Дата: 16.05.20 14:57
Оценка: 53 (1)
Здравствуйте, Shmj, Вы писали:

S>Пишут что сглупили, теперь хотят все исправить. Ваше мнение?


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

default(int?) = null
default(string?) = null
default(int) = 0
default(string) = ?


Из-за этого, компилятор не знает чем инициализировать значения ненулевых ссылочных типов, т.к. в системе типов нет такого понятия. И пока компилятор не научится понимять что

default(string?) = null
default(string) = string.Empty


вы не сможете это фичу использовать как следует нигде, кроме интерфейсных контрактов.
C# 8 и null-допустимость - ошибка на миллиард
От: Shmj Ниоткуда  
Дата: 12.05.20 18:38
Оценка: 5 (1)
https://m.habr.com/ru/company/piter/blog/501520/

Пишут что сглупили, теперь хотят все исправить. Ваше мнение?
Re[4]: C# 8 и null-допустимость - ошибка на миллиард
От: Sinclair Россия https://github.com/evilguest/
Дата: 13.05.20 12:39
Оценка: 5 (1)
Здравствуйте, vmpire, Вы писали:

V>Это понятно. Но возьмите какой-нибудь реальный существующий код крупного/среднего проекта. Пришло указание использовать новую фичу. Включили контроль. Попадала куча ошибок.

V>Как будет фиксить типовой средний разработчик? Правильно, понатыкает везде инициализацию в пустую строку, чтобы компилировалось.
Это если речь о строке. А если нет?
V>И вместо NRE будет затруднённый поиск ошшибок.
Ну, если этим парням сейчас NRE не мешает, то вряд ли помешает пустая строка. Ну, свалится у них код не с NRE, а с FileName cannot be empty, или с тем, что string.Length у них вернул нуль туда, куда нуль не принимают.

V>Проверка аргументов (которую Вы упомянули) отлично решает эту проблему, а заодно и с другими типами и другими видами ошибок в аргументах.

Решает, но только там, где она есть.
V>Жаль, CodeContracts забросили, как раз бы подошло.
Совершенно верно. Вот они NotNull contract вшили в компилятор.

V>Атрибут [NotNull] уже есть, можно было просто ввести его в язык.

Я так понимаю, их разочаровал уровень использования [NotNull]. Поэтому они решили пойти несколько более насильственным путём: дать способ массово зафорсить этот [NotNull].

V>Ну не пустую строку, а, например, пустой конструктор, который чаще всего есть.

Ну х.з. По мне так его как раз чаще всего нету; а если есть — то он производит вполне валидный объект, который отлично сработает.
Просто где-то был code path, когда этот мембер не инициализировался, а теперь такого code path не будет.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: C# 8 и null-допустимость - ошибка на миллиард
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.05.20 05:40
Оценка: 5 (1)
Здравствуйте, ·, Вы писали:
·>Какое-то плохое объяснение... Чем это принципиально отличается от:
·>Ну вот обратились мы к полю ._xx, а оно — "". Почему оно "" — да х.з. Где вместо "" может быть [], 0 и т.д.
Да, совершенно верно. "Почему _xx — чётно???". "Почему threadMask больше 12?" "Почему lastName не за-урл-енкожен?"
Хорошая, развитая система типов должна давать такие возможности выражать статически.
Увы — имеем ту, которую имеем. Nullable Ref — это попытка заклеить самую большую дыру в системе типов; это не замена полноценному статическому theorem-prover-grade анализу корректности, а попытка, грубо говоря, решить 30% проблем за 0.3% стоимости.

·>По-моему основная проблема, что null насильно добавляет ещё одно значение в область значений всех типов которое в подавляющем большинстве случаев не нужно, но заставляет явно об этом помнить каждый раз, усложняет код часто бессмысленными проверками и/или грозит падением. Притом, если скажем int/string/etc можно обернуть в класс и заставить его быть только в определённом диапазоне, то с null такой трюк не пройдёт, выразить кодом, что null тут нет или есть — не получится.

Ну, тут тоже не всё совсем так. Завёртывание в свой класс работает далеко не всегда — ну, потому что, например, сумма двух intLessThan14 даёт не инт и не intLessThan14, а intLessThan28, а это в терминах классов CLR не выразишь.
Но в целом — да, без non-null это всё вообще бессмысленно.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: C# 8 и null-допустимость - ошибка на миллиард
От: elmal  
Дата: 14.05.20 18:56
Оценка: 5 (1)
Здравствуйте, vmpire, Вы писали:

V>Я считаю, что самая большая ошибка в борьбе с NRE — это борьба с NRE.

Смотря как бороться. Если игнорить проблему, да, косяк. Но современный способ решения проблемы — если ссылка указывает на Object, то она гарантирована не может иметь null значение никогда физически. Если null допустим, то тип будет Object|Null или же Object?. И уже на этапе компиляции будет невозможно присвоить null. И далее, если у объекта Object? сделали проверку на null, в той ветке, где объект не null его тип становится Object и он уже взорваться дальше гарантированно не может.

Соответственно все очень неплохо получается и надежно, а также компактно. Говорю как тот, кто использует языки с подобным поведением уже больше 5 лет.
Re[2]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.05.20 15:59
Оценка: 5 (1)
Здравствуйте, Aquilaware, Вы писали:

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


S>>Пишут что сглупили, теперь хотят все исправить. Ваше мнение?


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


A>
A>default(int?) = null
A>default(string?) = null
A>default(int) = 0
A>default(string) = ?
A>


A>Из-за этого, компилятор не знает чем инициализировать значения ненулевых ссылочных типов, т.к. в системе типов нет такого понятия. И пока компилятор не научится понимять что


https://docs.microsoft.com/en-us/dotnet/csharp/nullable-migration-strategies#late-initialized-properties-data-transfer-objects-and-nullability

Initialize the property to null

As a terser alternative to using a nullable backing field, or if the library that instantiates your class is not compatible with that approach, you can simply initialize the property to null directly, with the help of the null-forgiving operator (!):

[Required]
public string FirstName { get; set; } = null!;

[Required]
public string LastName { get; set; } = null!;

public string? VehicleRegistration { get; set; }

You will never observe an actual null value at runtime except as a result of a programming bug, by accessing the property before it has been properly initialized.



В конструкторах ты должен их заполнять.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 16.05.2020 16:00 Serginio1 . Предыдущая версия .
Re[2]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 13.05.20 05:35
Оценка: :)
Здравствуйте, vmpire, Вы писали:

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


S>>https://m.habr.com/ru/company/piter/blog/501520/


S>>Пишут что сглупили, теперь хотят все исправить. Ваше мнение?

V>Я считаю, что самая большая ошибка в борьбе с NRE — это борьба с NRE.
V>Если заменить null на какое-нибудь значение, которое будет тихо пропускаться при обработке, то станет ещё хуже: ошибка никуда не денется, но вместо явного падения будет выдаваться неправильный результат где-то совсем в другом месте и отследить будет на порядок сложнее.
V>Ведь чтобы избежать ошибок компиляции 90% разработчиков просто понавтыкают при объявлении переменной инициализацию в пустую строку.

V>Да, часть таких ошибок отловит компилятор, но весьма малую часть. А отлов остальных значительно усложнится, и получится ещё более дорогая проблема.

V>Похожая ситуация была в джаве с явным объявлением exceptions. Насколько я смотрел в джавовский код, никто эти не пользуется, так как в мало-мальски сложной програме отследить это всё равно невозможно.
V>Точно также и с null — мало кто будет пользоваться новыми возможностями и основная проблема не пофиксится, но добавится новая

А в плюсах вполне себе используют указатели и ссылки и не слышал, чтобы кто-то говорил, что ссылки не нужны и из-за них появляются трудноуловимые ошибки.
Re[3]: C# 8 и null-допустимость - ошибка на миллиард
От: vmpire Россия  
Дата: 13.05.20 12:33
Оценка: +1
Здравствуйте, Sinclair, Вы писали:


S>>>Пишут что сглупили, теперь хотят все исправить. Ваше мнение?

V>>Я считаю, что самая большая ошибка в борьбе с NRE — это борьба с NRE.
V>>Если заменить null на какое-нибудь значение, которое будет тихо пропускаться при обработке, то станет ещё хуже: ошибка никуда не денется, но вместо явного падения будет выдаваться неправильный результат где-то совсем в другом месте и отследить будет на порядок сложнее.
S>Ну, фича вроде бы не про замену null на какое-нибудь значение. А про чёткий контроль контрактов:
Это понятно. Но возьмите какой-нибудь реальный существующий код крупного/среднего проекта. Пришло указание использовать новую фичу. Включили контроль. Попадала куча ошибок.
Как будет фиксить типовой средний разработчик? Правильно, понатыкает везде инициализацию в пустую строку, чтобы компилировалось.
И вместо NRE будет затруднённый поиск ошшибок.

S>Ну вот обратились мы к полю ._xx, а оно — null. Почему оно null — да х.з. Надо разматывать назад не только стек, а всю предысторию — откуда, что, куда.

Проверка аргументов (которую Вы упомянули) отлично решает эту проблему, а заодно и с другими типами и другими видами ошибок в аргументах.
Жаль, CodeContracts забросили, как раз бы подошло.

S>Это дорого и трудно. Куда лучше, если об этом нам скажет компилятор и заранее. Тогда у нас будет возможность обложить все места, откуда в наш ._хх может приехать null, явными проверками с throw ArgumentNullException.

Атрибут [NotNull] уже есть, можно было просто ввести его в язык.

V>>Ведь чтобы избежать ошибок компиляции 90% разработчиков просто понавтыкают при объявлении переменной инициализацию в пустую строку.

S>Ну, не всякую переменную можно инициализировать пустой строкой.
Ну не пустую строку, а, например, пустой конструктор, который чаще всего есть.
Re[5]: C# 8 и null-допустимость - ошибка на миллиард
От: · Великобритания  
Дата: 14.05.20 08:37
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Да, совершенно верно. "Почему _xx — чётно???". "Почему threadMask больше 12?" "Почему lastName не за-урл-енкожен?"

S>Хорошая, развитая система типов должна давать такие возможности выражать статически.
Я немного о другом. Даже такая недоразвитая система типов позволяет создать тип EvenNumber, UrlEncodedString — пользоваться неудобно, но можно. А вот NotNullableString — даже такой возможности нет.

S>·>По-моему основная проблема, что null насильно добавляет ещё одно значение в область значений всех типов которое в подавляющем большинстве случаев не нужно, но заставляет явно об этом помнить каждый раз, усложняет код часто бессмысленными проверками и/или грозит падением. Притом, если скажем int/string/etc можно обернуть в класс и заставить его быть только в определённом диапазоне, то с null такой трюк не пройдёт, выразить кодом, что null тут нет или есть — не получится.

S>Ну, тут тоже не всё совсем так. Завёртывание в свой класс работает далеко не всегда — ну, потому что, например, сумма двух intLessThan14 даёт не инт и не intLessThan14, а intLessThan28, а это в терминах классов CLR не выразишь.
Для большинства практических применений это уже слишком круто, это уже из области верификации... А там либо очень сложно писать код, либо верифицировать только частично. "Классическая" недоразвитая система типов вполне себе компромисс между юзабельностью и безопасностью.

S>Но в целом — да, без non-null это всё вообще бессмысленно.

Угу. Вроде бы мелочь, легко исправить, легко использовать, но традиционно напихали везде где только можно и в итоге сабж.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[10]: C# 8 и null-допустимость - ошибка на миллиард
От: · Великобритания  
Дата: 14.05.20 08:42
Оценка: +1
Здравствуйте, Serginio1, Вы писали:

S> Ну давай

S>void foo(ref int s)
S> что ты на null собрался проверять?
Так это ж int, он примитивный тип, он не может быть null. Этот ref вообще к теме не относится и никаких проблем не решает, так, сахар синтаксический.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: C# 8 и null-допустимость - ошибка на миллиард
От: Jericho113 Украина  
Дата: 15.05.20 10:18
Оценка: +1
Здравствуйте, Shmj, Вы писали:

S>https://m.habr.com/ru/company/piter/blog/501520/


S>Пишут что сглупили, теперь хотят все исправить. Ваше мнение?


Сглупили не они а Хоар и оттуда null прополз в основные мейнстримовые языки т.к.
авторы их побоялись изначально задать явную невозможность присваивания NULL потому что не хотели что бы девелоперы переучивались
(ну почему блин почти все создатели языков так этого боятся)

Так что они исправляют заимствованный косяк идущий имхо аж с алгола

Время покажет насколько удобно это будет... сейчас очень рано говорить
NetDigitally yours ....
Re: C# 8 и null-допустимость - ошибка на миллиард
От: student__  
Дата: 17.05.20 10:31
Оценка: -1
Так просто C# говно-язык. Нормальный язык недопускает null reference, by construction.
Re[3]: C# 8 и null-допустимость - ошибка на миллиард
От: Homunculus Россия  
Дата: 13.05.20 05:38
Оценка:
Здравствуйте, karbofos42, Вы писали:

K>А в плюсах вполне себе используют указатели и ссылки и не слышал, чтобы кто-то говорил, что ссылки не нужны и из-за них появляются трудноуловимые ошибки.


Не путай шарпников и сишников.
Re[3]: C# 8 и null-допустимость - ошибка на миллиард
От: vmpire Россия  
Дата: 13.05.20 11:06
Оценка:
Здравствуйте, karbofos42, Вы писали:

K>А в плюсах вполне себе используют указатели и ссылки и не слышал, чтобы кто-то говорил, что ссылки не нужны и из-за них появляются трудноуловимые ошибки.

Ну так я как раз и пишу, что не нужно решать несуществующие проблемы
Re[3]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.05.20 11:58
Оценка:
Здравствуйте, karbofos42, Вы писали:
K>А в плюсах вполне себе используют указатели и ссылки и не слышал, чтобы кто-то говорил, что ссылки не нужны и из-за них появляются трудноуловимые ошибки.
Ссылки и в C# есть и прекрасно работают. Указатели тоже существуют, но это уже унсейв.
Тут проблема в том, что есть методы в которые нужно передавать не null.
И как раз указав, что параметр должен быть не null то идет контроль на уровне компилятора.
Частично решается с помощью атрибутов [NotNull], для подсказки всяким решарперам и прочим. Но решили, что типы NotNull это правильнее.
Но это касается еще и возвращаемых значений.
Я в общем то согласен.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 13.05.2020 11:59 Serginio1 . Предыдущая версия .
Re[4]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 13.05.20 18:49
Оценка:
Здравствуйте, Serginio1, Вы писали:

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

K>>А в плюсах вполне себе используют указатели и ссылки и не слышал, чтобы кто-то говорил, что ссылки не нужны и из-за них появляются трудноуловимые ошибки.
S>Ссылки и в C# есть и прекрасно работают. Указатели тоже существуют, но это уже унсейв.
S>Тут проблема в том, что есть методы в которые нужно передавать не null.
S>И как раз указав, что параметр должен быть не null то идет контроль на уровне компилятора.
S>Частично решается с помощью атрибутов [NotNull], для подсказки всяким решарперам и прочим. Но решили, что типы NotNull это правильнее.
S>Но это касается еще и возвращаемых значений.
S>Я в общем то согласен.

так в плюсах ссылка — это указатель, который не null. Этого в шарпе нет и ref — совсем иное

void foo(A *a)
{
  // здесь a может быть null и нужно добавлять проверку
}

void foo(A &a)
{
  // здесь a не null и можно работать с объектом без доп. проверок
}
Re[4]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 13.05.20 18:55
Оценка:
Здравствуйте, vmpire, Вы писали:

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


K>>А в плюсах вполне себе используют указатели и ссылки и не слышал, чтобы кто-то говорил, что ссылки не нужны и из-за них появляются трудноуловимые ошибки.

V>Ну так я как раз и пишу, что не нужно решать несуществующие проблемы

ну, существующие проблемы — везде и всюду пишешь проверку на null в начале методов, лезешь в чужие методы, чтобы посмотреть что он там принимает, а что — нет.
Всё это в итоге падает на этапе выполнения и компилятор ничем не помогает.
Если кто-то что-то не проинициализировал, то немного позже вылезет ошибка, но такого кода, думаю, сильно меньше, чем NRE. С нормальными тестами это ничего не меняет.
Нововведение по сути практически синтаксический сахар. Кому не нравится — можно не использовать. Не вижу проблемы.
Атрибут NotNull слишком многословен и выглядит как костыль.
Re[5]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.05.20 20:14
Оценка:
Здравствуйте, karbofos42, Вы писали:



K>так в плюсах ссылка — это указатель, который не null. Этого в шарпе нет и ref — совсем иное


K>
K>void foo(A *a)
K>{
K>  // здесь a может быть null и нужно добавлять проверку
K>}

K>void foo(A &a)
K>{
K>  // здесь a не null и можно работать с объектом без доп. проверок
K>}
K>




в .Net есть два вида объектов ValueType (инт байт и прочее) и Reference type.

String это аналог вашего *char
String s=null это аналог
*char s=null;


Вызвав
foo(&s)

будет передан адрес переменной s в которой содержится null
но внутри метода можно установить значение
по сути там будет **char
a="чего то там"

это аналог С# варианта

foo(ref string s)
{
и здесь s== null но мы можем изменить значение переменной.
s= "Чего то там"
}


Суть в том, что если ты передаешь ссылку на валуе тип то у валуе типа не может быть null, а вот у ссылочного может.
Это все варианты с *Тип.

Вот ты и путаешь структуры с указателями на эти структуры.
Просто в C# классы это не структуры и по сути являются указателями на объекты в куче.
И они могут содержать null так же как и *char s=null;

От того, что ты ссылаешься на эту переменную, сама переменная содержит null
и солнце б утром не вставало, когда бы не было меня
Re[6]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 13.05.20 20:46
Оценка:
Здравствуйте, Serginio1, Вы писали:

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




K>>так в плюсах ссылка — это указатель, который не null. Этого в шарпе нет и ref — совсем иное


K>>
K>>void foo(A *a)
K>>{
K>>  // здесь a может быть null и нужно добавлять проверку
K>>}

K>>void foo(A &a)
K>>{
K>>  // здесь a не null и можно работать с объектом без доп. проверок
K>>}
K>>




S> в .Net есть два вида объектов ValueType (инт байт и прочее) и Reference type.


S>String это аналог вашего *char

S> String s=null это аналог
S>*char s=null;


S>Вызвав

S>foo(&s)

S> будет передан адрес переменной s в которой содержится null

S>но внутри метода можно установить значение
S>по сути там будет **char
S>a="чего то там"

S>это аналог С# варианта


S>foo(ref string s)

S>{
S> и здесь s== null но мы можем изменить значение переменной.
S> s= "Чего то там"
S>}


S>Суть в том, что если ты передаешь ссылку на валуе тип то у валуе типа не может быть null, а вот у ссылочного может.

S>Это все варианты с *Тип.

S> Вот ты и путаешь структуры с указателями на эти структуры.

S>Просто в C# классы это не структуры и по сути являются указателями на объекты в куче.
S>И они могут содержать null так же как и *char s=null;

S>От того, что ты ссылаешься на эту переменную, сама переменная содержит null


И причём здесь вот это вот всё? Как это связано с ссылками в плюсах?
вот накидал пример с одним и тем же объектом в куче:
http://cpp.sh/6gkmg
указатель можно и нужно проверять на null внутри метода, а ссылку можно считать корректной. Можно конечно извратиться и всё поломать, но это только специально если сделать.
Меня всегда удивляло почему сразу в шарпе ничего похожего не сделали и заставили везде эти проверки на null писать
Re[7]: C# 8 и null-допустимость - ошибка на миллиард
От: · Великобритания  
Дата: 13.05.20 21:22
Оценка:
Здравствуйте, karbofos42, Вы писали:

K>И причём здесь вот это вот всё? Как это связано с ссылками в плюсах?

K>вот накидал пример с одним и тем же объектом в куче:
K>http://cpp.sh/6gkmg
Да та же проблема, только хуже.

K>указатель можно и нужно проверять на null внутри метода,

Можно, да, как и в шарпе. Нужно — нет, не всегда, а иногда даже вредно.
Вот например код:

public: void f(A *a)
{
  if(a == null) return;
  for(million...times) {
    g(a);
  } 
}

private: void g(A *a)
{
//вот тут ты будешь проверять a==null?
}


K>а ссылку можно считать корректной. Можно конечно извратиться и всё поломать, но это только специально если сделать.

Да без всяких извратов — любое разыменование указателя может потенциально создать поломанную ссылку. Вот тут у тебя:
 foo2(*obj);

Ты забыл проверить obj на null при разыменовании. Конечно, в трёх срочках легко поглядеть глазками и увидеть что obj всегда безусловно присваивается, а в реальном коде строчек будет поболее, немного условных операторов и всё становится неочевидно. А компилятор никак тебе не поможет — в этом и беда.

K>Меня всегда удивляло почему сразу в шарпе ничего похожего не сделали и заставили везде эти проверки на null писать

Потому что это проблему не решает, скорее усугубляет.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: C# 8 и null-допустимость - ошибка на миллиард
От: varenikAA  
Дата: 14.05.20 00:31
Оценка:
Здравствуйте, Shmj, Вы писали:

S>https://m.habr.com/ru/company/piter/blog/501520/


S>Пишут что сглупили, теперь хотят все исправить. Ваше мнение?


Мой взгляд таков, что в C# это не приживется также как и в kotlin.
Есть прекрасная альтернатива в дотнете:
type Person = {
    Name : string
    Note : string option
}

type Date = System.DateTime
type Id = System.Int32

let report person =
    match person.Note with
        | None -> printfn "%s не содержит описания" person.Name
        | Some note -> printfn "%s (%s)" person.Name note


report {Name = "Alice"; Note = None }        
report {Name = "Bob"; Note = Some "Bad programmer" }  
report null // error FS0043: Тип "Person" не содержит собственное значение "null"


F#

1. записи
2. алиасы
3. необязательные значения
4. гораздо более приятный и лаконичный синтаксис
5. вообщем много вещей

Для гуя есть реактивный elm шаблон — по каждой команде вычисляется новое состояние и обновляется интерфейс.
под веб есть fable, под десктоп есть шаблон для авалонии.

PS но мне все больше нравится красота и лаконичность кложи и ее динамическая типизация.
Например, множественная диспетчеризация(мультиметоды) обсуждалась еще при проектировании C# 5, но как я понимаю этого до сих пор там нет.
В кложе даже возможна сигнальная обработка ошибок как чистом комон лиспе.
Нужно лишь начать мыслить шире.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[8]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 14.05.20 03:45
Оценка:
Здравствуйте, ·, Вы писали:
·>Можно, да, как и в шарпе. Нужно — нет, не всегда, а иногда даже вредно.
·>Вот например код:

·>
·>public: void f(A *a)
·>{
·>  if(a == null) return;
·>  for(million...times) {
·>    g(a);
·>  } 
·>}

·>private: void g(A *a)
·>{
·>//вот тут ты будешь проверять a==null?
·>}
·>


В методе g я так же постараюсь добавить проверку на null, если он не поддерживает такие входные данные. В итоге две проверки одного и того же будет.
Если бы в f изначально пришла ссылка, то не потребовалось бы ни одной проверки на null в этих методах.

·>Ты забыл проверить obj на null при разыменовании. Конечно, в трёх срочках легко поглядеть глазками и увидеть что obj всегда безусловно присваивается, а в реальном коде строчек будет поболее, немного условных операторов и всё становится неочевидно. А компилятор никак тебе не поможет — в этом и беда.


не забыл, а опустил этот момент, т.к. здесь в своём коде я точно знал, что указатель не равен null.
Зачем проверять на null указатель, который в начале метода инициализируется?
Если метод ожидает на вход не null-ссылку, то я должен проверить свои данные, а не разбираться в том, что умеет данный метод.
Если метод принимает указатель, то не понятно сразу — можно в него null передать или же нужно сначала в своём коде добавить проверку и не вызывать этот метод, чтобы дальше проверка на null не вывалила NRE.
В итоге проверки на null плодятся по цепочке вызова метода, когда можно было проверить только в одном месте и дальше передать не null ссылку.

K>>Меня всегда удивляло почему сразу в шарпе ничего похожего не сделали и заставили везде эти проверки на null писать

·>Потому что это проблему не решает, скорее усугубляет.

Я вижу только проблемы в коде, который десереализует не nullable свойства, которые никак не проверяются нигде и дальше некие default(T) не уходят бесконтрольно по коду, вызывая странный эффект.
Для этого достаточно десереализуемые свойства объявлять nullable и работать как раньше или настраивать сериализаторы (проставлять Required и т.п.).
Re[7]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 14.05.20 07:10
Оценка:
Здравствуйте, karbofos42, Вы писали:


S>>String это аналог вашего *char

S>> String s=null это аналог
S>>*char s=null;


S>>Вызвав

S>>foo(&s)

S>> будет передан адрес переменной s в которой содержится null

S>>но внутри метода можно установить значение
S>>по сути там будет **char
S>>a="чего то там"

S>>это аналог С# варианта


S>>foo(ref string s)

S>>{
S>> и здесь s== null но мы можем изменить значение переменной.
S>> s= "Чего то там"
S>>}


S>>Суть в том, что если ты передаешь ссылку на валуе тип то у валуе типа не может быть null, а вот у ссылочного может.

S>>Это все варианты с *Тип.

S>> Вот ты и путаешь структуры с указателями на эти структуры.

S>>Просто в C# классы это не структуры и по сути являются указателями на объекты в куче.
S>>И они могут содержать null так же как и *char s=null;

S>>От того, что ты ссылаешься на эту переменную, сама переменная содержит null


K>И причём здесь вот это вот всё? Как это связано с ссылками в плюсах?

K>вот накидал пример с одним и тем же объектом в куче:
K>http://cpp.sh/6gkmg
K>указатель можно и нужно проверять на null внутри метода, а ссылку можно считать корректной. Можно конечно извратиться и всё поломать, но это только специально если сделать.
K>Меня всегда удивляло почему сразу в шарпе ничего похожего не сделали и заставили везде эти проверки на null писать

Еще раз в C#

void foo(ref А s)
это аналог
void foo(A &a)

Это по сути адрес переменной. Ты не согласен?

Если передается
void foo(*A &a)

то интересует не адрес переменной а её содержимое. Толку то её считать корректно, когда нужно проверять содержимое переменной.
и солнце б утром не вставало, когда бы не было меня
Re[8]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 14.05.20 08:01
Оценка:
Здравствуйте, Serginio1, Вы писали:
S> Еще раз в C#

S>void foo(ref А s)

S>это аналог
S>void foo(A &a)

S>Это по сути адрес переменной. Ты не согласен?


Не согласен.
В ref A я могу передать null, а в A& — нет.
Соответственно в шарпе в foo(ref A a) мне первой строчкой нужно проверять что a == null и кидать NRE, а в плюсах проверка такая не нужна.
В ref A я могу создать новый объект A и поменять внешнюю переменную, а в A& — нет.
ref A — это указатель на указатель, а не ссылка в плюсах.
Re[9]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 14.05.20 08:10
Оценка:
Здравствуйте, karbofos42, Вы писали:

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

S>> Еще раз в C#

S>>void foo(ref А s)

S>>это аналог
S>>void foo(A &a)

S>>Это по сути адрес переменной. Ты не согласен?


K>Не согласен.

А что тогда передается по ссылке?
K>В ref A я могу передать null, а в A& — нет.
K>Соответственно в шарпе в foo(ref A a) мне первой строчкой нужно проверять что a == null и кидать NRE, а в плюсах проверка такая не нужна.
K>В ref A я могу создать новый объект A и поменять внешнюю переменную, а в A& — нет.
Да?

https://metanit.com/cpp/tutorial/2.14.php

После установления ссылки мы можем через нее манипулировать самим объектом, на который она ссылается:

int main()
{
    int number = 5;
    int &refNumber = number;
    std::cout << refNumber << std::endl; // 5
    refNumber = 20;
    std::cout << number << std::endl;   // 20
         
    return 0;
}

K>ref A — это указатель на указатель, а не ссылка в плюсах.

ref A это как раз ссылка на переменную. То есть адрес переменной.

Ну давай
void foo(ref int s)

что ты на null собрался проверять?
и солнце б утром не вставало, когда бы не было меня
Re[10]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 14.05.20 08:17
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> А что тогда передается по ссылке?


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

S> Ну давай

S>void foo(ref int s)

S> что ты на null собрался проверять?


Ну и зачем тут int нарисовался?

пусть у нас будет класс A.
В шарпе можно написать так:

void foo(ref A a)
{
  if (a == null)
    throw new ArgumentNullException();

  a = new A();
}

...
A a = new A();
A b = a;
foo(ref a);
// Что тут вернёт b == a; ?
b = null;
foo(ref b); // а вот так я могу передать null

на плюсах с аргументом типа A &a ничего такого нет и внешнюю переменную не подменишь и внутри метода не нужно проверять, что ссылка на null указывает.
Re[6]: C# 8 и null-допустимость - ошибка на миллиард
От: Евгений Акиньшин grapholite.com
Дата: 14.05.20 09:02
Оценка:
Здравствуйте, ·, Вы писали:

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


·>Я немного о другом. Даже такая недоразвитая система типов позволяет создать тип EvenNumber, UrlEncodedString — пользоваться неудобно, но можно. А вот NotNullableString — даже такой возможности нет.


А если как-нибудь так?


public struct NotNullableString
{
    public NotNullableString(string value)
    {
      Value = value ?? string.Empty;
    }

    public string Value { get; }
}


или так:

public struct NotNullable<T>
    where T : class
{
    public NotNullable(T value)
    {
      if (value == null)
        throw new ArgumentNullException();
      Value = value;
    }

    public T Value { get; }
}


Но пользоваться не удобно, прям совсем. Пусть лучше в языке будет.
Не шалю, никого не трогаю, починяю примус Diagrams Designer for iPad and Windows 10
Re[11]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 14.05.20 09:35
Оценка:
Здравствуйте, ·, Вы писали:

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


S>> Ну давай

S>>void foo(ref int s)
S>> что ты на null собрался проверять?
·> Так это ж int, он примитивный тип, он не может быть null. Этот ref вообще к теме не относится и никаких проблем не решает, так, сахар синтаксический.

Еще один.
Что передает ссылка?
Ответ адрес переменной.
ref это же и делает

Или ты не согласен?

*char s=null;
void foo(*char &s)

что будет в s
и солнце б утром не вставало, когда бы не было меня
Re[11]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 14.05.20 09:38
Оценка:
Здравствуйте, karbofos42, Вы писали:

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


S>> А что тогда передается по ссылке?


K>Я не согласен, что это аналог. Техническая реализация меня мало интересует.

K>В плюсах ссылки от указателей тоже ничем не отличаются в итоге, но в плане использования дают свои особенности.

S>> Ну давай

S>>void foo(ref int s)

S>> что ты на null собрался проверять?


K>Ну и зачем тут int нарисовался?


K>пусть у нас будет класс A.

K>В шарпе можно написать так:

K>
K>void foo(ref A a)
K>{
K>  if (a == null)
K>    throw new ArgumentNullException();

K>  a = new A();
K>}

K>...
K>A a = new A();
K>A b = a;
K>foo(ref a);
K>// Что тут вернёт b == a; ?
K>b = null;
K>foo(ref b); // а вот так я могу передать null
K>

K>на плюсах с аргументом типа A &a ничего такого нет и внешнюю переменную не подменишь и внутри метода не нужно проверять, что ссылка на null указывает.

Еще раз

https://metanit.com/cpp/tutorial/3.3.php

Передача по ссылке позволяет возвратить из функции сразу несколько значений. Также передача параметров по ссылке является более эффективной при передаче очень больших объектов. Поскольку в этом случае не происходит копирования значений, а функция использует сам объект, а не его значение.
От передачи аргументов по ссылке следует отличать передачу ссылок в качестве аргументов:

int main()
{
    int a = 4;
    int b = 5;
    std::cout << "Before square: a = " << a << "\tb=" << b << std::endl;
    square(a, b);
    std::cout << "After square: a = " << a << "\tb=" << b << std::endl;
 
    return 0;
}
void square(int &a, int &b)
{
    a = a * a;
    b = b * b;
    std::cout << "In square: a = " << a << "\tb=" << b << std::endl;
}


Изменяются значения.

void square(*int &a, *int &b)
{
    *a = *a * *a;
    *b = *b * *b;
}


Тебе также придется проверять а и b на null

Вот в C# все ссылочные типы это указатели
и солнце б утром не вставало, когда бы не было меня
Re[12]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 14.05.20 09:50
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Еще раз


S>https://metanit.com/cpp/tutorial/3.3.php


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

S>От передачи аргументов по ссылке следует отличать передачу ссылок в качестве аргументов:

И зачем мне этот сомнительный текст?

S>
S>void square(*int &a, *int &b)
S>{
S>    *a = *a * *a;
S>    *b = *b * *b;
S>}
S>


Если я правильно помню плюсы, то этот код вообще не соберётся.

S> Тебе также придется проверять а и b на null


S> Вот в C# все ссылочные типы это указатели


Я привёл конкретный пример того, что мне не нравится и чего в шарпе легко и просто не достичь.
В ответ какая-то околесица вместо такого же прямого решения. В чём прикол?
Re[13]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 14.05.20 10:01
Оценка:
Здравствуйте, karbofos42, Вы писали:


K>И зачем мне этот сомнительный текст?

То что передаются адреса переменных
S>>
S>>void square(*int &a, *int &b)
S>>{
S>>    *a = *a * *a;
S>>    *b = *b * *b;
S>>}
S>>


K>Если я правильно помню плюсы, то этот код вообще не соберётся.


S>> Тебе также придется проверять а и b на null


S>> Вот в C# все ссылочные типы это указатели


K>Я привёл конкретный пример того, что мне не нравится и чего в шарпе легко и просто не достичь.

K>В ответ какая-то околесица вместо такого же прямого решения. В чём прикол?

Раз так как ты утверждаешь, что

void square(*int &a, *int &b)
{
    *a = *a * *a;
    *b = *b * *b;
}


То

пример

void square(int &a, int &b)

void square(ref int a, ref int  b)
{
    a = a * a;
    b = b * b;
}


Прекрасно работает и в C#.
Но может работать и с сылочными типами то есть

void square(*char &a, *char &b)

void square(ref string a, ref string b)
и солнце б утром не вставало, когда бы не было меня
Re[9]: C# 8 и null-допустимость - ошибка на миллиард
От: · Великобритания  
Дата: 14.05.20 10:07
Оценка:
Здравствуйте, karbofos42, Вы писали:

K>В методе g я так же постараюсь добавить проверку на null, если он не поддерживает такие входные данные.

Ключевое слово выделил. Да, все стараются писать безбажный код, но иногда что-то идёт не так. Проблема сабжа в том, что очень легко сделать так, чтобы старался компилятор, а не разработчик. Но везде напихали null — без какой либо явной необходимости, просто традиционно.

K>В итоге две проверки одного и того же будет.

И вполне может просесть производительность на пустом месте.

K>Если бы в f изначально пришла ссылка, то не потребовалось бы ни одной проверки на null в этих методах.

Зато потребовалось бы везде где есть вызовы этого f с разыменованием. Плюс помимо аргументов есть локальные переменные, поля классов, везде эта проблема.

K>·>Ты забыл проверить obj на null при разыменовании. Конечно, в трёх срочках легко поглядеть глазками и увидеть что obj всегда безусловно присваивается, а в реальном коде строчек будет поболее, немного условных операторов и всё становится неочевидно. А компилятор никак тебе не поможет — в этом и беда.

K>не забыл, а опустил этот момент, т.к. здесь в своём коде я точно знал, что указатель не равен null.
Потому что код иногда меняют, притом не только ты со своим "постараюсь", но и менее старательные разработчики. В реальном проекте через год эти 3 строчки превратятся в 300, что-то отрефакторится, выделится в отдельные методы, методы зареюзаются и в итоге твоё "точно знал" превратиться в "эээ... ну наверное... я надеюсь...".

K>Зачем проверять на null указатель, который в начале метода инициализируется?

Верно, этим должен заниматься компилятор. Если бы компилятор это проверял, то некорректный код бы просто не скомпилился.

K>Если метод ожидает на вход не null-ссылку, то я должен проверить свои данные, а не разбираться в том, что умеет данный метод.

С какого перепугу "должен"? Скорее "должен постараться не забыть".

K>Если метод принимает указатель, то не понятно сразу — можно в него null передать или же нужно сначала в своём коде добавить проверку и не вызывать этот метод, чтобы дальше проверка на null не вывалила NRE.

А если это не метод, а коллекция указателей? Они могут быть null или нет?

K>>>Меня всегда удивляло почему сразу в шарпе ничего похожего не сделали и заставили везде эти проверки на null писать

K>·>Потому что это проблему не решает, скорее усугубляет.
K>Я вижу только проблемы в коде, который десереализует не nullable свойства, которые никак не проверяются нигде и дальше некие default(T) не уходят бесконтрольно по коду, вызывая странный эффект.
K>Для этого достаточно десереализуемые свойства объявлять nullable и работать как раньше или настраивать сериализаторы (проставлять Required и т.п.).
Проблема в том, что ты не можешь выразить в _языке_ понятие not-null или nullable в системе типов. ref проблему не решает, т.к. проверок компилятором оно не добавляет, просто соглашение, которое никак формально не проверяется, кроме как "поглядел глазами, вроде всё ок". А усугубляет т.к. теперь у нас появилось понятие битых ссылок и ещё больше UB.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[7]: C# 8 и null-допустимость - ошибка на миллиард
От: · Великобритания  
Дата: 14.05.20 10:09
Оценка:
Здравствуйте, Евгений Акиньшин, Вы писали:

ЕА>Но пользоваться не удобно, прям совсем. Пусть лучше в языке будет.

Вот именно. А сабж в том, накой null вообще есть.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[12]: C# 8 и null-допустимость - ошибка на миллиард
От: · Великобритания  
Дата: 14.05.20 10:14
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>·> Так это ж int, он примитивный тип, он не может быть null. Этот ref вообще к теме не относится и никаких проблем не решает, так, сахар синтаксический.

S>Еще один.
S> Что передает ссылка?
S>Ответ адрес переменной.
S> ref это же и делает
S>Или ты не согласен?
Согласен. Круто, конечно. А дальше-то что? Как это решает сабж?! Ну адрес не null, а то что адресуется — null. Т.е. вместо "хрен знает чего" у нас появилась "точно известный адрес хрен знает чего". А смысл?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[13]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 14.05.20 10:29
Оценка:
Здравствуйте, ·, Вы писали:

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


S>>·> Так это ж int, он примитивный тип, он не может быть null. Этот ref вообще к теме не относится и никаких проблем не решает, так, сахар синтаксический.

S>>Еще один.
S>> Что передает ссылка?
S>>Ответ адрес переменной.
S>> ref это же и делает
S>>Или ты не согласен?
·>Согласен. Круто, конечно. А дальше-то что? Как это решает сабж?! Ну адрес не null, а то что адресуется — null. Т.е. вместо "хрен знает чего" у нас появилась "точно известный адрес хрен знает чего". А смысл?

Человек утверждает что в С++ защита от null есть в сылке, а в C# нет.

Я утверждаю, что

void square(ref string a, ref string b)


аналогично
void square(*char &a, *char &b)


и все равно нужно проверять а и b на null
и солнце б утром не вставало, когда бы не было меня
Re[14]: C# 8 и null-допустимость - ошибка на миллиард
От: · Великобритания  
Дата: 14.05.20 10:55
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>·>Согласен. Круто, конечно. А дальше-то что? Как это решает сабж?! Ну адрес не null, а то что адресуется — null. Т.е. вместо "хрен знает чего" у нас появилась "точно известный адрес хрен знает чего". А смысл?

S>Человек утверждает что в С++ защита от null есть в сылке, а в C# нет.
А, да, с этим согласен. ref вообще к сабжу не относится. Ни там, ни там защиты от null нет. В плюсах вообще защиты никакой нет, там UB.

S>аналогично

S>
S>void square(*char &a, *char &b)
S>

Ну да, синтаксис неверный. Должно быть "char *&a" афаир.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[7]: C# 8 и null-допустимость - ошибка на миллиард
От: · Великобритания  
Дата: 14.05.20 10:57
Оценка:
Здравствуйте, Евгений Акиньшин, Вы писали:

ЕА>Но пользоваться не удобно, прям совсем. Пусть лучше в языке будет.

И, как я понимаю, не только не удобно, но и не всегда возможно. Захочешь положить это в коллекцию, асинхронщина какая-нибдуь, передать в другой тред... и придётся обернуть в класс.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[14]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 14.05.20 10:57
Оценка:
Здравствуйте, Serginio1, Вы писали:

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



K>>И зачем мне этот сомнительный текст?

S>То что передаются адреса переменных
S>>>
S>>>void square(*int &a, *int &b)
S>>>{
S>>>    *a = *a * *a;
S>>>    *b = *b * *b;
S>>>}
S>>>


K>>Если я правильно помню плюсы, то этот код вообще не соберётся.


S>>> Тебе также придется проверять а и b на null


S>>> Вот в C# все ссылочные типы это указатели


K>>Я привёл конкретный пример того, что мне не нравится и чего в шарпе легко и просто не достичь.

K>>В ответ какая-то околесица вместо такого же прямого решения. В чём прикол?

S>Раз так как ты утверждаешь, что


S>
S>void square(*int &a, *int &b)
S>{
S>    *a = *a * *a;
S>    *b = *b * *b;
S>}
S>


S>То


S> пример


S>void square(int &a, int &b)


S>
S>void square(ref int a, ref int  b)
S>{
S>    a = a * a;
S>    b = b * b;
S>}
S>


S>Прекрасно работает и в C#.

S>Но может работать и с сылочными типами то есть

S>void square(*char &a, *char &b)


S>void square(ref string a, ref string b)


Напиши мне аналог вот этого http://cpp.sh/9ejjk на шарпе
С таким же количеством необходимых проверок на null и контролем на уровне компилятора.
Без разницы — ref там будет или еще какое-то волшебное ключевое слово.
И не int или char, а так же любой класс, т.е. ссылочный тип.
Re[10]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 14.05.20 11:22
Оценка:
Здравствуйте, ·, Вы писали:

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


K>>В методе g я так же постараюсь добавить проверку на null, если он не поддерживает такие входные данные.

·>Ключевое слово выделил. Да, все стараются писать безбажный код, но иногда что-то идёт не так. Проблема сабжа в том, что очень легко сделать так, чтобы старался компилятор, а не разработчик. Но везде напихали null — без какой либо явной необходимости, просто традиционно.

Поэтому я и говорю о том, что ссылочные типы так же должны уметь быть не nullable как какой-нибудь int

K>>В итоге две проверки одного и того же будет.

·>И вполне может просесть производительность на пустом месте.

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

K>>Если бы в f изначально пришла ссылка, то не потребовалось бы ни одной проверки на null в этих методах.

·>Зато потребовалось бы везде где есть вызовы этого f с разыменованием. Плюс помимо аргументов есть локальные переменные, поля классов, везде эта проблема.

где требуется разыменование, там мой метод, с которым я сейчас работаю, а не год назад. Здесь и сейчас я знаю нужно ли проверить указатель на null или нет.
без notnull же мне придётся сначала посмотреть на описание метода или начало его тела, чтобы понять — можно туда null передать или же требуется так же в моём методе подавить точно такую же проверку, как перед разыменованием.

K>>·>Ты забыл проверить obj на null при разыменовании. Конечно, в трёх срочках легко поглядеть глазками и увидеть что obj всегда безусловно присваивается, а в реальном коде строчек будет поболее, немного условных операторов и всё становится неочевидно. А компилятор никак тебе не поможет — в этом и беда.

K>>не забыл, а опустил этот момент, т.к. здесь в своём коде я точно знал, что указатель не равен null.
·>Потому что код иногда меняют, притом не только ты со своим "постараюсь", но и менее старательные разработчики. В реальном проекте через год эти 3 строчки превратятся в 300, что-то отрефакторится, выделится в отдельные методы, методы зареюзаются и в итоге твоё "точно знал" превратиться в "эээ... ну наверное... я надеюсь...".

без разыименования я получил бы ровно такую же ошибку в Runtime, только уже в методе, который бы получил нежданный null.
разница в том, что тут нужно выполнить операцию по переводу из nullable в notnullable, а сейчас можно забыть и случайно кинуть null дальше.

K>>Зачем проверять на null указатель, который в начале метода инициализируется?

·>Верно, этим должен заниматься компилятор. Если бы компилятор это проверял, то некорректный код бы просто не скомпилился.

K>>Если метод ожидает на вход не null-ссылку, то я должен проверить свои данные, а не разбираться в том, что умеет данный метод.

·>С какого перепугу "должен"? Скорее "должен постараться не забыть".

должен — значит моя обязанность только в том, чтобы преобразовать свои данные в подходящие для метода типы. В сам метод лазить не обязательно.

K>>Если метод принимает указатель, то не понятно сразу — можно в него null передать или же нужно сначала в своём коде добавить проверку и не вызывать этот метод, чтобы дальше проверка на null не вывалила NRE.

·>А если это не метод, а коллекция указателей? Они могут быть null или нет?

В Runtime будет понятно

K>>>>Меня всегда удивляло почему сразу в шарпе ничего похожего не сделали и заставили везде эти проверки на null писать

K>>·>Потому что это проблему не решает, скорее усугубляет.
K>>Я вижу только проблемы в коде, который десереализует не nullable свойства, которые никак не проверяются нигде и дальше некие default(T) не уходят бесконтрольно по коду, вызывая странный эффект.
K>>Для этого достаточно десереализуемые свойства объявлять nullable и работать как раньше или настраивать сериализаторы (проставлять Required и т.п.).
·>Проблема в том, что ты не можешь выразить в _языке_ понятие not-null или nullable в системе типов. ref проблему не решает, т.к. проверок компилятором оно не добавляет, просто соглашение, которое никак формально не проверяется, кроме как "поглядел глазами, вроде всё ок". А усугубляет т.к. теперь у нас появилось понятие битых ссылок и ещё больше UB.

сейчас со всякими int нет UB, а если по аналогии default(class) возвращать не null, а вызывать конструктор и создавать объект, то всё сломается?
Re[15]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 14.05.20 11:55
Оценка:
Здравствуйте, karbofos42, Вы писали:

K>Напиши мне аналог вот этого http://cpp.sh/9ejjk на шарпе

K>С таким же количеством необходимых проверок на null и контролем на уровне компилятора.
K>Без разницы — ref там будет или еще какое-то волшебное ключевое слово.
K>И не int или char, а так же любой класс, т.е. ссылочный тип.

int main()
{
    A *obj = new A(0); // Создаём объект примерно как в C#
    
    cout << obj->Value << endl;
    
    // тут так уж и быть проверим, что указатель не null перед получением ссылки
    if (obj == nullptr)
        throw "NullReferenceException";
    foo1(*obj);
    // тут на null не нужно проверять, т.к. при передаче по ссылке указатель не мог стать null, т.е. переменная obj не менялась
    cout << obj->Value << endl;
}



Ты же проверку делаешь на null
if (obj == nullptr)
throw "NullReferenceException";

А как без неё

и а это у тебя по сути структура это аналог decimal
и передаешь ты не obj, а указатель на структуру.
Все твои методы по сути принмают ссылку на Структуру.

Аналог в шарпе все тоже как и у тебя
void foo(ref A d)
{
}

A[] b= new A[1];
foo(ref b[0])

Просто классы в С++ и структуры суть одного и того же. В C# это другое.
Структуры боксятся , сборщик мусора отрабатывает по разному (2 копии получается)

Но твои

void foo2(A& a)

это аналог

void foo2(ref int a)

Так как A это структура!!
А аналог C# это A*

В C# ввели ссылочных локальных переменных.
То есть можно получить ссылку на структуру и работать с ней.
Передавать в параметрах, возвращать из функций, привязываться к локальным переменным

class Program
    {
        static int[] testArray = new int[] { 1, 2, 3 };
        static void Test(ref int d)
        {
            d = 5;
        }

        static ref int Test( int d)
        {
            return ref testArray[d];
        }

        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            int r = 4;

            ref int d = ref r;
            Test(ref d);

            ref int d2 = ref Test(1);

            Test(ref d2);

            Console.WriteLine(testArray[1].ToString());
        }
    }
и солнце б утром не вставало, когда бы не было меня
Re[16]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 14.05.20 12:20
Оценка:
Здравствуйте, Serginio1, Вы писали:

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


K>>Напиши мне аналог вот этого http://cpp.sh/9ejjk на шарпе

K>>С таким же количеством необходимых проверок на null и контролем на уровне компилятора.
K>>Без разницы — ref там будет или еще какое-то волшебное ключевое слово.
K>>И не int или char, а так же любой класс, т.е. ссылочный тип.

S>
S>int main()
S>{
S>    A *obj = new A(0); // Создаём объект примерно как в C#
    
S>    cout << obj->Value << endl;
    
S>    // тут так уж и быть проверим, что указатель не null перед получением ссылки
S>    if (obj == nullptr)
S>        throw "NullReferenceException";
S>    foo1(*obj);
S>    // тут на null не нужно проверять, т.к. при передаче по ссылке указатель не мог стать null, т.е. переменная obj не менялась
S>    cout << obj->Value << endl;
S>}
S>



S>Ты же проверку делаешь на null

S> if (obj == nullptr)
S> throw "NullReferenceException";

S>А как без неё


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

S>и а это у тебя по сути структура это аналог decimal

S>и передаешь ты не obj, а указатель на структуру.
S>Все твои методы по сути принмают ссылку на Структуру.

Там чёрным по белому написано class, значит у меня класс, а не структура, тем более, что в плюсах структура — то же самое, что и класс.

S> Аналог в шарпе все тоже как и у тебя

S>void foo(ref A d)
S>{
S>}

S>A[] b= new A[1];

S>foo(ref b[0])

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

S> Просто классы в С++ и структуры суть одного и того же. В C# это другое.

S>Структуры боксятся , сборщик мусора отрабатывает по разному (2 копии получается)

S>Но твои


S>void foo2(A& a)


S>это аналог


S>void foo2(ref int a)


S>Так как A это структура!!

S>А аналог C# это A*

т.е. когда A *a = new A(); // это создание объекта класса
A &b = *a; // это уже структура, хотя и область памяти и тип данных тот же?)

S> В C# ввели ссылочных локальных переменных.

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

S>
S>class Program
S>    {
S>        static int[] testArray = new int[] { 1, 2, 3 };
S>        static void Test(ref int d)
S>        {
S>            d = 5;
S>        }

S>        static ref int Test( int d)
S>        {
S>            return ref testArray[d];
S>        }

S>        static void Main(string[] args)
S>        {
S>            Console.WriteLine("Hello World!");
S>            int r = 4;

S>            ref int d = ref r;
S>            Test(ref d);

S>            ref int d2 = ref Test(1);

S>            Test(ref d2);

S>            Console.WriteLine(testArray[1].ToString());
S>        }
S>    }
S>


Это не аналог, т.к. тут нет класса, который был в примере на плюсах.
Я же говорю: мне параллельно на внутреннюю организацию и т.п. В плюсах создаёшь класс с наследованием и всем таким, дальше передаёшь ссылку на объект этого класса и её не нужно проверять на null во всех методах.
Пусть хоть компилятор внутри втихаря сам генерирует проверки на null, которые сейчас пишутся вручную, но в языке должна быть возможность работать с объектами, которые не могут быть null.
Re[17]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 14.05.20 12:46
Оценка:
Здравствуйте, karbofos42, Вы писали:



S>>и а это у тебя по сути структура это аналог decimal

S>>и передаешь ты не obj, а указатель на структуру.
S>>Все твои методы по сути принмают ссылку на Структуру.

K>Там чёрным по белому написано class, значит у меня класс, а не структура, тем более, что в плюсах структура — то же самое, что и класс.


На заборе тоже написано. В чем разница в С++ между классом и структурой?

S>> Аналог в шарпе все тоже как и у тебя

S>>void foo(ref A d)
S>>{
S>>}

S>>A[] b= new A[1];

S>>foo(ref b[0])

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

K>Если А — класс, то поведение совсем другое и проверки на null никуда не уходят, а на структурах без наследования далеко не уедешь.

Еще раз классы в C# и С++ разные понятия. Классы С++ по сути C# структуры. Размещаются на стеке и в куче

S>> Просто классы в С++ и структуры суть одного и того же. В C# это другое.

S>>Структуры боксятся , сборщик мусора отрабатывает по разному (2 копии получается)

S>>Но твои


S>>void foo2(A& a)


S>>это аналог


S>>void foo2(ref int a)


S>>Так как A это структура!!

S>>А аналог C# это A*

K>т.е. когда A *a = new A(); // это создание объекта класса

K>A &b = *a; // это уже структура, хотя и область памяти и тип данных тот же?)

Да это аналог С#
ref A b= ref a;

S>> В C# ввели ссылочных локальных переменных.

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

S>>
S>>class Program
S>>    {
S>>        static int[] testArray = new int[] { 1, 2, 3 };
S>>        static void Test(ref int d)
S>>        {
S>>            d = 5;
S>>        }

S>>        static ref int Test( int d)
S>>        {
S>>            return ref testArray[d];
S>>        }

S>>        static void Main(string[] args)
S>>        {
S>>            Console.WriteLine("Hello World!");
S>>            int r = 4;

S>>            ref int d = ref r;
S>>            Test(ref d);

S>>            ref int d2 = ref Test(1);

S>>            Test(ref d2);

S>>            Console.WriteLine(testArray[1].ToString());
S>>        }
S>>    }
S>>


K>Это не аналог, т.к. тут нет класса, который был в примере на плюсах.

K>Я же говорю: мне параллельно на внутреннюю организацию и т.п. В плюсах создаёшь класс с наследованием и всем таким, дальше передаёшь ссылку на объект этого класса и её не нужно проверять на null во всех методах.
K>Пусть хоть компилятор внутри втихаря сам генерирует проверки на null, которые сейчас пишутся вручную, но в языке должна быть возможность работать с объектами, которые не могут быть null.

Еще раз классы С++ это аналог C# структуры. Только можно наследоваться и размещать в куче.
Но в С++ и нет сборщика мусора, боксинга итд. Нельзя сравнивать несравниваемое.

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

Заменяю structure A и все тоже что и на C++

Но на самом деле в будущем может и сделают классы которые будут размещаться на стеке.
https://xoofx.com/blog/2015/10/08/stackalloc-for-class-with-roslyn-and-coreclr/
и солнце б утром не вставало, когда бы не было меня
Re[18]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 14.05.20 13:08
Оценка:
Здравствуйте, Serginio1, Вы писали:

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




S>>>и а это у тебя по сути структура это аналог decimal

S>>>и передаешь ты не obj, а указатель на структуру.
S>>>Все твои методы по сути принмают ссылку на Структуру.

K>>Там чёрным по белому написано class, значит у меня класс, а не структура, тем более, что в плюсах структура — то же самое, что и класс.


S>На заборе тоже написано. В чем разница в С++ между классом и структурой?


тем, что структуры = класс с публичными по умолчанию методами и полями. Наследование есть? Значит класс

S>>> Аналог в шарпе все тоже как и у тебя

S>>>void foo(ref A d)
S>>>{
S>>>}

S>>>A[] b= new A[1];

S>>>foo(ref b[0])

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

K>>Если А — класс, то поведение совсем другое и проверки на null никуда не уходят, а на структурах без наследования далеко не уедешь.

S> Еще раз классы в C# и С++ разные понятия. Классы С++ по сути C# структуры. Размещаются на стеке и в куче


Это какие-то самостоятельно выдуманные определения классов и структур?

S>>> Просто классы в С++ и структуры суть одного и того же. В C# это другое.

S>>>Структуры боксятся , сборщик мусора отрабатывает по разному (2 копии получается)

S>>>Но твои


S>>>void foo2(A& a)


S>>>это аналог


S>>>void foo2(ref int a)


S>>>Так как A это структура!!

S>>>А аналог C# это A*

K>>т.е. когда A *a = new A(); // это создание объекта класса

K>>A &b = *a; // это уже структура, хотя и область памяти и тип данных тот же?)

S>Да это аналог С#

S>ref A b= ref a;

т.е. одна и та же область памяти и класс и структура одновременно?

S>>> В C# ввели ссылочных локальных переменных.

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

S>>>
S>>>class Program
S>>>    {
S>>>        static int[] testArray = new int[] { 1, 2, 3 };
S>>>        static void Test(ref int d)
S>>>        {
S>>>            d = 5;
S>>>        }

S>>>        static ref int Test( int d)
S>>>        {
S>>>            return ref testArray[d];
S>>>        }

S>>>        static void Main(string[] args)
S>>>        {
S>>>            Console.WriteLine("Hello World!");
S>>>            int r = 4;

S>>>            ref int d = ref r;
S>>>            Test(ref d);

S>>>            ref int d2 = ref Test(1);

S>>>            Test(ref d2);

S>>>            Console.WriteLine(testArray[1].ToString());
S>>>        }
S>>>    }
S>>>


K>>Это не аналог, т.к. тут нет класса, который был в примере на плюсах.

K>>Я же говорю: мне параллельно на внутреннюю организацию и т.п. В плюсах создаёшь класс с наследованием и всем таким, дальше передаёшь ссылку на объект этого класса и её не нужно проверять на null во всех методах.
K>>Пусть хоть компилятор внутри втихаря сам генерирует проверки на null, которые сейчас пишутся вручную, но в языке должна быть возможность работать с объектами, которые не могут быть null.

S>Еще раз классы С++ это аналог C# структуры. Только можно наследоваться и размещать в куче.


Напоминает бабушку, которая была бы дедушкой, если бы...

S>Но в С++ и нет сборщика мусора, боксинга итд. Нельзя сравнивать несравниваемое.


S>А ветка как ра о том, что ввели ссылочные типы которые не могут быть null. И за проверкой следит компилятор.


S>Заменяю structure A и все тоже что и на C++


S>Но на самом деле в будущем может и сделают классы которые будут размещаться на стеке.

S>https://xoofx.com/blog/2015/10/08/stackalloc-for-class-with-roslyn-and-coreclr/

Я просто привёл пример синтаксиса, который есть в другом языке и успешно используется.
Причём тут стек, структуры, сборщики мусора и всё прочее?
В плюсах нужные notnull объекты давным давно есть в виде ссылок. В шарпе вот только только родили аналог.
Только оказывается его нельзя было сделать, потому что в шарпе классы — это классы, а не структуры
Re[11]: C# 8 и null-допустимость - ошибка на миллиард
От: · Великобритания  
Дата: 14.05.20 13:21
Оценка:
Здравствуйте, karbofos42, Вы писали:

K>>>В методе g я так же постараюсь добавить проверку на null, если он не поддерживает такие входные данные.

K>·>Ключевое слово выделил. Да, все стараются писать безбажный код, но иногда что-то идёт не так. Проблема сабжа в том, что очень легко сделать так, чтобы старался компилятор, а не разработчик. Но везде напихали null — без какой либо явной необходимости, просто традиционно.
K>Поэтому я и говорю о том, что ссылочные типы так же должны уметь быть не nullable как какой-нибудь int
Ну и сабж об этом.

K>>>В итоге две проверки одного и того же будет.

K>·>И вполне может просесть производительность на пустом месте.
K>и лишняя писанина добивает. IDE конечно позволяет автоматом сгенерировать проверки, но это тоже нужно поддерживать.
И на test coverage report без слёз смотреть нельзя будет. Сабж.

K>>>Если бы в f изначально пришла ссылка, то не потребовалось бы ни одной проверки на null в этих методах.

K>·>Зато потребовалось бы везде где есть вызовы этого f с разыменованием. Плюс помимо аргументов есть локальные переменные, поля классов, везде эта проблема.
K>где требуется разыменование, там мой метод, с которым я сейчас работаю, а не год назад. Здесь и сейчас я знаю нужно ли проверить указатель на null или нет.
_Ты_ знаешь. Но можешь легко забыть, компилятор тебе не поможет.

K>без notnull же мне придётся сначала посмотреть на описание метода или начало его тела, чтобы понять — можно туда null передать или же требуется так же в моём методе подавить точно такую же проверку, как перед разыменованием.

Хуже того. Ты можешь посмотреть сейчас, а потом, когда кто-нибудь где-нибудь что-нибудь как-нибудь поменяет — всё внезапно поломается, а компилятор даже не пискнет.

K>·>Потому что код иногда меняют, притом не только ты со своим "постараюсь", но и менее старательные разработчики. В реальном проекте через год эти 3 строчки превратятся в 300, что-то отрефакторится, выделится в отдельные методы, методы зареюзаются и в итоге твоё "точно знал" превратиться в "эээ... ну наверное... я надеюсь...".

K>без разыименования я получил бы ровно такую же ошибку в Runtime, только уже в методе, который бы получил нежданный null.
Притом это в c# ошибка, в плюсах просто UB — код может и не падать, а давать какие-то невменяемые результаты в каких-то совершенно неожиданных местах.

K>>>Зачем проверять на null указатель, который в начале метода инициализируется?

K>·>Верно, этим должен заниматься компилятор. Если бы компилятор это проверял, то некорректный код бы просто не скомпилился.
K>>>Если метод ожидает на вход не null-ссылку, то я должен проверить свои данные, а не разбираться в том, что умеет данный метод.
K>·>С какого перепугу "должен"? Скорее "должен постараться не забыть".
K>должен — значит моя обязанность только в том, чтобы преобразовать свои данные в подходящие для метода типы. В сам метод лазить не обязательно.
А лучше если это будет обязанность компилятора. То что в метод принимающий Date нельзя передать String — это компилятор проверит, а вот null внезапно приходится разбирать разработчику.

K>>>Если метод принимает указатель, то не понятно сразу — можно в него null передать или же нужно сначала в своём коде добавить проверку и не вызывать этот метод, чтобы дальше проверка на null не вывалила NRE.

K>·>А если это не метод, а коллекция указателей? Они могут быть null или нет?
K>В Runtime будет понятно
Тогда уж надо на JavaScript переходить.

K>>>>>Меня всегда удивляло почему сразу в шарпе ничего похожего не сделали и заставили везде эти проверки на null писать

K>>>·>Потому что это проблему не решает, скорее усугубляет.
K>>>Я вижу только проблемы в коде, который десереализует не nullable свойства, которые никак не проверяются нигде и дальше некие default(T) не уходят бесконтрольно по коду, вызывая странный эффект.
K>>>Для этого достаточно десереализуемые свойства объявлять nullable и работать как раньше или настраивать сериализаторы (проставлять Required и т.п.).
K>·>Проблема в том, что ты не можешь выразить в _языке_ понятие not-null или nullable в системе типов. ref проблему не решает, т.к. проверок компилятором оно не добавляет, просто соглашение, которое никак формально не проверяется, кроме как "поглядел глазами, вроде всё ок". А усугубляет т.к. теперь у нас появилось понятие битых ссылок и ещё больше UB.

K>сейчас со всякими int нет UB, а если по аналогии default(class) возвращать не null, а вызывать конструктор и создавать объект, то всё сломается?

Тут проблема немного в другом. Если тебя не устраивает то что int==0 по умолчанию и ты хочешь, чтобы в какой-то части программы число было без нулей, то ты можешь завести новый тип NonZeroInt, инкапсулирующий int с нужным поведением и использовать его повсюду безопасно, с контролем компилятора. В случае null это просто невозможно.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[19]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 14.05.20 14:53
Оценка:
Здравствуйте, karbofos42, Вы писали:



S>>А ветка как ра о том, что ввели ссылочные типы которые не могут быть null. И за проверкой следит компилятор.


S>>Заменяю structure A и все тоже что и на C++


S>>Но на самом деле в будущем может и сделают классы которые будут размещаться на стеке.

S>>https://xoofx.com/blog/2015/10/08/stackalloc-for-class-with-roslyn-and-coreclr/

K>Я просто привёл пример синтаксиса, который есть в другом языке и успешно используется.

K>Причём тут стек, структуры, сборщики мусора и всё прочее?
Что касается классов в С++ и C# это разные вещи. В одном есть сборка мусора в другом нет.
Интерфейсы реализуются по другому итд.

Что бы работать объектом класса как со структурой нужно добавлять информацию для сборщика мусора.
Объекты класса не размещаются на стеке итд. Разная архитектура.

K>В плюсах нужные notnull объекты давным давно есть в виде ссылок. В шарпе вот только только родили аналог.

K>Только оказывается его нельзя было сделать, потому что в шарпе классы — это классы, а не структуры

В твоем примере так или иначе нужнапроверка на null.
В шапрпе с вводом NotNull классов это не нужно.

У меня коллега сейчас пишет на С и C#. И просто радуется как ребенок когда переходит на C#
Говорит какой же это детский язык!!
и солнце б утром не вставало, когда бы не было меня
Re[20]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 14.05.20 16:11
Оценка:
Здравствуйте, Serginio1, Вы писали:

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




S>>>А ветка как ра о том, что ввели ссылочные типы которые не могут быть null. И за проверкой следит компилятор.


S>>>Заменяю structure A и все тоже что и на C++


S>>>Но на самом деле в будущем может и сделают классы которые будут размещаться на стеке.

S>>>https://xoofx.com/blog/2015/10/08/stackalloc-for-class-with-roslyn-and-coreclr/

K>>Я просто привёл пример синтаксиса, который есть в другом языке и успешно используется.

K>>Причём тут стек, структуры, сборщики мусора и всё прочее?
S>Что касается классов в С++ и C# это разные вещи. В одном есть сборка мусора в другом нет.
S>Интерфейсы реализуются по другому итд.

S> Что бы работать объектом класса как со структурой нужно добавлять информацию для сборщика мусора.

S>Объекты класса не размещаются на стеке итд. Разная архитектура.

Когда захотели, они добавили сахар в виде int? и т.п. Nullable<T>
Кто им мешал сделать человеческий синтаксис, а потом при компиляции уже генерировать нужные NRE и т.п., чтобы люди вручную это не писали?

K>>В плюсах нужные notnull объекты давным давно есть в виде ссылок. В шарпе вот только только родили аналог.

K>>Только оказывается его нельзя было сделать, потому что в шарпе классы — это классы, а не структуры

S>В твоем примере так или иначе нужнапроверка на null.

S>В шапрпе с вводом NotNull классов это не нужно.

И как же в шарпе будет кастоваться без такой проверки Null класс в его NotNull аналог?
Эта проверка собственно и сейчас есть при конвертации int? в int
Re[21]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 14.05.20 17:13
Оценка:
Здравствуйте, karbofos42, Вы писали:





S>>В твоем примере так или иначе нужнапроверка на null.

S>>В шапрпе с вводом NotNull классов это не нужно.

K>И как же в шарпе будет кастоваться без такой проверки Null класс в его NotNull аналог?

K>Эта проверка собственно и сейчас есть при конвертации int? в int

Если нужно кастоваться разумеется проверка на null. Но на то он и каст.
Ну разумеется если ты работаешь с нуллабля типами тебе приходится проверять. Но большинство работает с int и не работают с int?

Тоже самое и с С++ если ты работаешь с *A. Тебе нужно сделать проверку на null.
Другое дело, что сишники привыкли работать не с кучей, а со стеком. Структура не может быть null


Нужно просто технику программирования поменять
https://docs.microsoft.com/ru-ru/dotnet/csharp/nullable-references
https://docs.microsoft.com/ru-ru/dotnet/csharp/nullable-migration-strategies

https://docs.microsoft.com/en-us/archive/msdn-magazine/2018/february/essential-net-csharp-8-0-and-nullable-reference-types
то есть будет тоже самое

static string? GetNullableString()

static void Тест1(string s)
{
// проверка на null не нужна
Тест2(s);
}

static void Тест2(string s)
{
// проверка на null не нужна
}


var s=GetNullableString();

 if (s==null)
   вызовем исключение 


Тест1(s!);


Найди различия с твоим примером
и солнце б утром не вставало, когда бы не было меня
Отредактировано 14.05.2020 17:44 Serginio1 . Предыдущая версия . Еще …
Отредактировано 14.05.2020 17:42 Serginio1 . Предыдущая версия .
Re[3]: C# 8 и null-допустимость - ошибка на миллиард
От: AlexGin Беларусь  
Дата: 14.05.20 18:05
Оценка:
Здравствуйте, karbofos42, Вы писали:

K>А в плюсах вполне себе используют указатели и ссылки и не слышал, чтобы кто-то говорил, что ссылки не нужны и из-за них появляются трудноуловимые ошибки.


В отличие от C#, ссылки в C++ НЕ могут быть неинициализированными.
Что же касается указателей (пришедших из Си) — то их проверка на NULL является вполне себе нормальной практикой в C++.
Re[22]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 14.05.20 21:16
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Найди различия с твоим примером


Так я про это и писал изначально.
Плюсы были просто как пример того, что тема рабочая
Re[23]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 15.05.20 07:25
Оценка:
Здравствуйте, karbofos42, Вы писали:

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


S>>Найди различия с твоим примером


K>Так я про это и писал изначально.

K>Плюсы были просто как пример того, что тема рабочая

Еще раз твой пример со структурами , мой пример с классами! Нет никакого приведения к структуре.
Как ты будешь работать со строками, массивами, массивами указателей? Твой подход не спасает от проверки на null.

Со структурами тоже ввели переменные ссылки, которые полностью соответствуют твоему примеру. Так, что вашему С++ еще догонять и догонять.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 15.05.2020 7:30 Serginio1 . Предыдущая версия . Еще …
Отредактировано 15.05.2020 7:27 Serginio1 . Предыдущая версия .
Re[24]: C# 8 и null-допустимость - ошибка на миллиард
От: karbofos42 Россия  
Дата: 15.05.20 08:48
Оценка:
Здравствуйте, Serginio1, Вы писали:

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


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


S>>>Найди различия с твоим примером


K>>Так я про это и писал изначально.

K>>Плюсы были просто как пример того, что тема рабочая

S> Еще раз твой пример со структурами , мой пример с классами! Нет никакого приведения к структуре.

S>Как ты будешь работать со строками, массивами, массивами указателей? Твой подход не спасает от проверки на null.

S>Со структурами тоже ввели переменные ссылки, которые полностью соответствуют твоему примеру. Так, что вашему С++ еще догонять и догонять.


Не надоело еще выдумывать свои классификации и определения?
В шарп ввели возможность делать ссылочные типы NotNull на уровне компилятора.
Это круто и замечательно, жаль, что изначально этого не было. Всё.
Re[25]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 15.05.20 08:58
Оценка:
Здравствуйте, karbofos42, Вы писали:

K>В шарп ввели возможность делать ссылочные типы NotNull на уровне компилятора.

K>Это круто и замечательно, жаль, что изначально этого не было. Всё.

Вот а ветка то как раз о том, null-допустимость — ошибка на миллиард.
Рад, что ты согласился, что это не ошибка, а преимущество.
и солнце б утром не вставало, когда бы не было меня
Re[3]: C# 8 и null-допустимость - ошибка на миллиард
От: vmpire Россия  
Дата: 15.05.20 10:23
Оценка:
Здравствуйте, elmal, Вы писали:

V>>Я считаю, что самая большая ошибка в борьбе с NRE — это борьба с NRE.

E>Смотря как бороться. Если игнорить проблему, да, косяк.
Так проблемы-то нет. Точнее, есть, но другая, более общая.
Если переменную не проинициализировали, а стали использовать, то это ошибка, независимо от того, какой это тип. ReferenceType тут ничем не особенный.
Если, например, это int, который должен быть проинициализирован, но там 0, и это приводит к неправильному поведению программы, это то же самое, что непроинициализированная строка, которая приводит к неправильному поведению.
Сейчас с ReferenceType даже лучше, потому, что программа падает, вместо того, чтобы выдавать втихую неверный результат.

E>Но современный способ решения проблемы — если ссылка указывает на Object, то она гарантирована не может иметь null значение никогда физически. Если null допустим, то тип будет Object|Null или же Object?. И уже на этапе компиляции будет невозможно присвоить null. И далее, если у объекта Object? сделали проверку на null, в той ветке, где объект не null его тип становится Object и он уже взорваться дальше гарантированно не может.

Да, часть потенциальных ошибок проверка компилятором покроет. Но никто не мешал сделать ту же самую проверку по атрибуту [NotNull], и ЕМНИП, какие-то средства статического анализа так уже и делали.
И это, конечно, хорошо, как и всякое выявление ошибок при статическом анализе. Но для этого не обязательно было менять язык.
Но, в силу обстоятельств, про которые я уже написал, есть у меня основания считать, что вреда от этой фичи будет не меньше, чем пользы.

E>Соответственно все очень неплохо получается и надежно, а также компактно. Говорю как тот, кто использует языки с подобным поведением уже больше 5 лет.

В том то и дело, что в языках, где эта возможность есть изначально, проблемы не будет.
А в С#, где уже есть немалая база кода и куча программистов, которые привыкли уже к существующему поведению, проблемы будут.
Re[4]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 15.05.20 10:47
Оценка:
Здравствуйте, vmpire, Вы писали:

E>>Соответственно все очень неплохо получается и надежно, а также компактно. Говорю как тот, кто использует языки с подобным поведением уже больше 5 лет.

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

Ну любые нововведения не сразу используются. Можно начинать с новых проектах, классов.
и солнце б утром не вставало, когда бы не было меня
Re[4]: C# 8 и null-допустимость - ошибка на миллиард
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.05.20 15:42
Оценка:
Здравствуйте, vmpire, Вы писали:

V>Если переменную не проинициализировали, а стали использовать, то это ошибка, независимо от того, какой это тип. ReferenceType тут ничем не особенный.

Во вех взрослых языках уже даво есть zero-init. Так что "неинициализированных переменных" в понимании низкоуровневых языков не былвает.
Более того компиятор C# с самого начала ругается на то, что ты обащается к переменной ссылочного типа, котрой не было присвоено значение.

V>Сейчас с ReferenceType даже лучше, потому, что программа падает, вместо того, чтобы выдавать втихую неверный результат.

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


V>Да, часть потенциальных ошибок проверка компилятором покроет. Но никто не мешал сделать ту же самую проверку по атрибуту [NotNull], и ЕМНИП, какие-то средства статического анализа так уже и делали.

Я тебе даже бльше скажу, новая фича и есть атрибут notnull, только работает немного не так. Ты должен явно указать где может быть null. На уровне .NET типов разницы нет.

V>И это, конечно, хорошо, как и всякое выявление ошибок при статическом анализе. Но для этого не обязательно было менять язык.

V>Но, в силу обстоятельств, про которые я уже написал, есть у меня основания считать, что вреда от этой фичи будет не меньше, чем пользы.
Только ты эти основания не написал

V>А в С#, где уже есть немалая база кода и куча программистов, которые привыкли уже к существующему поведению, проблемы будут.

Для них фича необязательная.
Re[5]: C# 8 и null-допустимость - ошибка на миллиард
От: vmpire Россия  
Дата: 15.05.20 18:04
Оценка:
Здравствуйте, gandjustas, Вы писали:


V>>Если переменную не проинициализировали, а стали использовать, то это ошибка, независимо от того, какой это тип. ReferenceType тут ничем не особенный.

G>Во вех взрослых языках уже даво есть zero-init.
C/C++ — довольно взрослые языки

G>Так что "неинициализированных переменных" в понимании низкоуровневых языков не былвает.

G>Более того компиятор C# с самого начала ругается на то, что ты обащается к переменной ссылочного типа, котрой не было присвоено значение.
Возможно, я некорректно выразился, хотя, КМК было понятно по контексту. Имелась в виду не любая инициализация, а инициализация тем, что нужно по смыслу программы.
Потому, что с точки зрения zero-init и ReferenceTypes тоже уже проинициализированы.

V>>Сейчас с ReferenceType даже лучше, потому, что программа падает, вместо того, чтобы выдавать втихую неверный результат.

G>Проблема не в локальных переменных, а в параметрах и возвращаемых значениях.
G>Функции часто возвращают null, а программисты часто принимают null в качестве параметра и не проверяют.
G>Поэтому nre просиходит зачастую не там где ошибка, а гораздо ниже по стеку вызовов или вообще в другой части кода.
Спрасибо, конечно, но я как раз про это и говорил
Автор: vmpire
Дата: 12.05.20


V>>Да, часть потенциальных ошибок проверка компилятором покроет. Но никто не мешал сделать ту же самую проверку по атрибуту [NotNull], и ЕМНИП, какие-то средства статического анализа так уже и делали.

G>Я тебе даже бльше скажу, новая фича и есть атрибут notnull, только работает немного не так. Ты должен явно указать где может быть null. На уровне .NET типов разницы нет.
Я в курсе, спасибо.

V>>И это, конечно, хорошо, как и всякое выявление ошибок при статическом анализе. Но для этого не обязательно было менять язык.

V>>Но, в силу обстоятельств, про которые я уже написал, есть у меня основания считать, что вреда от этой фичи будет не меньше, чем пользы.
G>Только ты эти основания не написал
тут
Автор: vmpire
Дата: 12.05.20


V>>А в С#, где уже есть немалая база кода и куча программистов, которые привыкли уже к существующему поведению, проблемы будут.

G>Для них фича необязательная.
Так для них как раз эта проблема и существует. Для "илиты", у которых 20 лет опыта, которые пишут программы с нуля, без жёстких временных ограничений, с кучей тестов и на всех новых технологиях проблемы NRE, собственно, и нет.
Re: C# 8 и null-допустимость - ошибка на миллиард
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.05.20 17:40
Оценка:
Здравствуйте, Shmj, Вы писали:

S>https://m.habr.com/ru/company/piter/blog/501520/

S>Пишут что сглупили, теперь хотят все исправить. Ваше мнение?

Решение правильное. Чем больше проект тем полезнее будет эта фича. Ведь в больших проектах обычный коммит (пул-реквест) может идти пол дня, день. И если даже все покрыто тестами, время сэкономленное компилятором будет существенным. А вот реализация, похоже, будет на троечку.

Кроме контроля нулабельности нужно еще продвигать идею ML-я — все (ну, насколько это возможно) значения должны быть инициализированными. А Шарп с его мюьтабельностью по умолчанию и разными инициализаторами (подвигающими не писать конструкторы) плохо для этого приспособлен. Плюс наличие массивов в которых принципиально будут null — это не комильфо.

Плюс для реализации контроля нужен не хилый анализ, который МС, похоже, пока не осилил.

Еще одна проблема оператор "уверен, что не null". Боюсь его будут совать всюду без разбора и это все испортит.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.05.20 17:49
Оценка:
Здравствуйте, VladD2, Вы писали:


VD>Кроме контроля нулабельности нужно еще продвигать идею ML-я — все (ну, насколько это возможно) значения должны быть инициализированными. А Шарп с его мюьтабельностью по умолчанию и разными инициализаторами (подвигающими не писать конструкторы) плохо для этого приспособлен. Плюс наличие массивов в которых принципиально будут null — это не комильфо.


Ну массивы особо и не нужны достаточно List<string> и Span<string>. Добавлять в лист можешь только NotNull
VD>Плюс для реализации контроля нужен не хилый анализ, который МС, похоже, пока не осилил.

VD>Еще одна проблема оператор "уверен, что не null". Боюсь его будут совать всюду без разбора и это все испортит.


Ну оператор нужен что бы предупреждения не выдавать, а инициализировать должен в конструкторе. Ну и чем дольше будут пользоваться еще чего нибудь придумают
и солнце б утром не вставало, когда бы не было меня
Re[3]: C# 8 и null-допустимость - ошибка на миллиард
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.05.20 17:52
Оценка:
Здравствуйте, karbofos42, Вы писали:

K>А в плюсах вполне себе используют указатели и ссылки и не слышал, чтобы кто-то говорил, что ссылки не нужны и из-за них появляются трудноуловимые ошибки.


Ты поди и про оверквотинг не слышал.

А так правильно, потому как ошибки скорее из-за указателей.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 17.05.20 10:53
Оценка:
Здравствуйте, student__, Вы писали:

__>Так просто C# говно-язык. Нормальный язык недопускает null reference, by construction.

Огласи такие языки
и солнце б утром не вставало, когда бы не было меня
Re[2]: C# 8 и null-допустимость - ошибка на миллиард
От: Shmj Ниоткуда  
Дата: 17.05.20 10:58
Оценка:
Здравствуйте, student__, Вы писали:

__>Так просто C# говно-язык. Нормальный язык недопускает null reference, by construction.


Это вы про Haskell?
Re[2]: C# 8 и null-допустимость - ошибка на миллиард
От: Sharov Россия  
Дата: 17.05.20 11:25
Оценка:
Здравствуйте, Kolesiki, Вы писали:

K>Кто именно сглупил и что исправляют??


Tony Hoare.
Кодом людям нужно помогать!
Re[3]: C# 8 и null-допустимость - ошибка на миллиард
От: student__  
Дата: 17.05.20 13:37
Оценка:
Здравствуйте, Serginio1, Вы писали:

__>>Так просто C# говно-язык. Нормальный язык недопускает null reference, by construction.

S>Огласи такие языки

Rust же! Его safe подмножество.
Re[4]: C# 8 и null-допустимость - ошибка на миллиард
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 17.05.20 14:17
Оценка:
Здравствуйте, student__, Вы писали:

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


__>>>Так просто C# говно-язык. Нормальный язык недопускает null reference, by construction.

S>>Огласи такие языки

__>Rust же! Его safe подмножество.

Ну вот в C# тоже сейчас есть NotNull подмножество

http://rustbook.ru/ch19-01-unsafe-rust.html
и солнце б утром не вставало, когда бы не было меня
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.