Минутка WTF-20: Меньше кода - меньше ошибок
От: Sinix  
Дата: 06.11.17 16:08
Оценка: 181 (6) +1 :)))
Давно не виделись
Автор: Sinix
Дата: 28.02.17
, угу.

Буду краток.
        // c# 7.1
        static bool IsDefault<T>(T value) => Equals(value, default);

        static void Main(string[] args)
        {
            Console.WriteLine(IsDefault(0));
            Console.ReadKey();
        }


Вопрос стандартный: что не так-то?
минутка wtf
Re: Минутка WTF-20: Меньше кода - меньше ошибок
От: Jack128  
Дата: 06.11.17 16:11
Оценка: 48 (1) +2
Здравствуйте, Sinix, Вы писали:

S>Давно не виделись
Автор: Sinix
Дата: 28.02.17
, угу.


S>Буду краток.

S>
S>        // c# 7.1
S>        static bool IsDefault<T>(T value) => Equals(value, default);

S>        static void Main(string[] args)
S>        {
S>            Console.WriteLine(IsDefault(0));
S>            Console.ReadKey();
S>        }
S>


S>Вопрос стандартный: что не так-то?


Отвечать без компиляции ??
  Скрытый текст
Тогда предположу, что default здесь = default(object), тогда Equals((object)0, null) == false
Отредактировано 06.11.2017 16:16 Jack128 . Предыдущая версия .
Re: Минутка WTF-20: Меньше кода - меньше ошибок
От: vasmann  
Дата: 06.11.17 16:22
Оценка: 53 (2) +1
Здравствуйте, Sinix, Вы писали:

S>Давно не виделись
Автор: Sinix
Дата: 28.02.17
, угу.


S>Буду краток.

S>
S>        // c# 7.1
S>        static bool IsDefault<T>(T value) => Equals(value, default);

S>        static void Main(string[] args)
S>        {
S>            Console.WriteLine(IsDefault(0));
S>            Console.ReadKey();
S>        }
S>


S>Вопрос стандартный: что не так-то?


Предположу, что вызовется Equals(object)
Поскольку компилятор не знает (нет ограничения where) что тип может быть значимым. Поэтому всё компилирует как для object-ов. Ну и соответственно 10 == null что есть false.
Re[2]: Минутка WTF-20: Меньше кода - меньше ошибок
От: Sinix  
Дата: 06.11.17 16:42
Оценка:
Здравствуйте, Jack128, Вы писали:

J>Отвечать без компиляции ??

J><Спойлер>
Угу. Студия, впрочем, настаивает на обратном. Невезучая диагностика какая-то.
Re: Минутка WTF-20: Меньше кода - меньше ошибок
От: Sharov Россия  
Дата: 06.11.17 16:44
Оценка: +1 :)
Здравствуйте, Sinix, Вы писали:

S>Вопрос стандартный: что не так-то?


Ответ стандартный: внезапный boxing.
Кодом людям нужно помогать!
Re[2]: Минутка WTF-20: Меньше кода - меньше ошибок
От: vasmann  
Дата: 06.11.17 16:53
Оценка:
Здравствуйте, Sharov, Вы писали:

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


S>>Вопрос стандартный: что не так-то?


S>Ответ стандартный: внезапный boxing.



Нет, не боксинг. То как компилируются шаблонные типа/методы.
Если нет ограничения (where), то компилируется всё, как для object типа. Поскольку компилятор не может делать предположений о том, какие типы будут передаваться в runtime
Если в ограничении указан where T: SomeClass то будут компилироваться методы для SomeClass (например можно встрять если иметь иерархию классов у которых переопределены операторы equals, но не заворачивать эти реализации через virtual Equals). Тут уже компилятор знает, что как минимум SomeClass будет, а не object общий, потому так.
Re[2]: Минутка WTF-20: Меньше кода - меньше ошибок
От: Sinix  
Дата: 06.11.17 17:00
Оценка: +1
Здравствуйте, Sharov, Вы писали:

S>>Вопрос стандартный: что не так-то?


S>Ответ стандартный: внезапный boxing.

Аки "Пушкин/Гладиолус" в чтогдекогда
Re[2]: Минутка WTF-20: Меньше кода - меньше ошибок
От: yenik  
Дата: 07.11.17 07:49
Оценка:
V>Предположу, что вызовется Equals(object)
V>Поскольку компилятор не знает (нет ограничения where) что тип может быть значимым. Поэтому всё компилирует как для object-ов. Ну и соответственно 10 == null что есть false.

А почему так работает правильно?

static bool IsDefault<T>(T value) => Equals(value, default(T));

Тут тоже нет where.
Re[3]: Минутка WTF-20: Меньше кода - меньше ошибок
От: _NN_ www.nemerleweb.com
Дата: 07.11.17 08:01
Оценка:
Здравствуйте, yenik, Вы писали:

V>>Предположу, что вызовется Equals(object)

V>>Поскольку компилятор не знает (нет ограничения where) что тип может быть значимым. Поэтому всё компилирует как для object-ов. Ну и соответственно 10 == null что есть false.

Y>А почему так работает правильно?


Y>
Y>static bool IsDefault<T>(T value) => Equals(value, default(T));
Y>

Y>Тут тоже нет where.

Тут же явно указан default(T) .
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: Минутка WTF-20: Меньше кода - меньше ошибок
От: yenik  
Дата: 07.11.17 08:40
Оценка:
V>>>Предположу, что вызовется Equals(object)
V>>>Поскольку компилятор не знает (нет ограничения where) что тип может быть значимым. Поэтому всё компилирует как для object-ов. Ну и соответственно 10 == null что есть false.

Y>>А почему так работает правильно?


Y>>
Y>>static bool IsDefault<T>(T value) => Equals(value, default(T));
Y>>

Y>>Тут тоже нет where.

_NN>Тут же явно указан default(T) .


А T — ссылочный или структурный? Это же не указано.

Да, собственно, ответ уже дан: http://rsdn.org/forum/dotnet/6956070.1
Автор: Jack128
Дата: 06.11.17


В доке сказано.

You can now omit the type on the right-hand side of the initialization:
C#

Func<string, bool> whereClause = default;


Но в случае с Equals(value, default) компилятор не может угадать тип и выбирает object.Equals(value, default(object)).
Отредактировано 07.11.2017 8:57 yenik . Предыдущая версия .
Re[5]: Минутка WTF-20: Меньше кода - меньше ошибок
От: _NN_ www.nemerleweb.com
Дата: 07.11.17 08:55
Оценка:
Здравствуйте, yenik, Вы писали:

Код без сахара вопросов ведь не вызывает ?
static bool IsDefault<T>(T value){
 T d = default(T);
 return Equals(value, d); // Работает как надо
}


Или надо смотреть IL:
Equals(value, default);

        IL_0000: ldarg.0
        IL_0001: box !!T
        IL_0006: ldnull
        IL_0007: call bool [mscorlib]System.Object::Equals(object, object)


Equals(value, default(T));

        // Method begins at RVA 0x2050
        // Code size 26 (0x1a)
        .maxstack 2
        .locals init (
            [0] !!T
        )

        IL_0000: ldarg.0
        IL_0001: box !!T
        IL_0006: ldloca.s 0
        IL_0008: initobj !!T
        IL_000e: ldloc.0
        IL_000f: box !!T
        IL_0014: call bool [mscorlib]System.Object::Equals(object, object)
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Минутка WTF-20: Меньше кода - меньше ошибок
От: vasmann  
Дата: 07.11.17 12:29
Оценка: +1
Здравствуйте, yenik, Вы писали:

V>>Предположу, что вызовется Equals(object)

V>>Поскольку компилятор не знает (нет ограничения where) что тип может быть значимым. Поэтому всё компилирует как для object-ов. Ну и соответственно 10 == null что есть false.

Y>А почему так работает правильно?


Y>
Y>static bool IsDefault<T>(T value) => Equals(value, default(T));
Y>

Y>Тут тоже нет where.

Это ж разные сценарии.

Equals(value, default) — означает вызывать метод Equals c первым параметром value и вторым "по умолчанию" для типа второго аргумента. Т.е Equals(object, object) будет вызван как Equals(value, default(object))
Во втором случае вы явно указываете какого типа значение по умолчанию нужно брать.
Re: Минутка WTF-20: Меньше кода - меньше ошибок
От: Kolesiki  
Дата: 07.11.17 15:43
Оценка: :)
Здравствуйте, Sinix, Вы писали:

S> static bool IsDefault<T>(T value) => Equals(value, default);


Если код выглядит правильно, а работает — неправильно, ткнуть в него носом всех этих Липпертов и как в школе: "Переписывай заново, двоечник!".
Re: Минутка WTF-20: Меньше кода - меньше ошибок
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.11.17 16:56
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>Давно не виделись
Автор: Sinix
Дата: 28.02.17
, угу.


S>Буду краток.

S>
S>        // c# 7.1
S>        static bool IsDefault<T>(T value) => Equals(value, default);

S>        static void Main(string[] args)
S>        {
S>            Console.WriteLine(IsDefault(0));
S>            Console.ReadKey();
S>        }
S>

default(T)?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Минутка WTF-20: Меньше кода - меньше ошибок
От: Sinix  
Дата: 07.11.17 18:01
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>default(T)?

Оно. В реальной жизни выглядит как-то так.
Re[3]: Минутка WTF-20: Меньше кода - меньше ошибок
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.11.17 23:56
Оценка: 56 (2) +1
Здравствуйте, vasmann, Вы писали:

V>Нет, не боксинг. То как компилируются шаблонные типа/методы.

V>Если нет ограничения (where), то компилируется всё, как для object типа. Поскольку компилятор не может делать предположений о том, какие типы будут передаваться в runtime

where тут не причем. Для T без проблем можно правильно сформировать дефолтное значение. Тут проблема в Equals. Она не обобщенная, а принимает два object. Соответственно компилятор не может вывести тип для default и подставляет null (для object). Ну, а Equals считает 0 и null разными значениями (не С++ все же).

Если задать тип явно default(T) или использовать дженерик-метод:
static bool IsDefault<T>(T value) => EqualityComparer<T>.Default.Equals(value, default);

то компилятор сможет вывести типы и все будет пучком.

По уму компилятору нужно бы давать предупреждение о том, что default подставляется в место где требуется object и что лучше явно задать null.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Отредактировано 08.11.2017 23:58 VladD2 . Предыдущая версия .
Re[2]: Минутка WTF-20: Меньше кода - меньше ошибок
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.11.17 15:22
Оценка: :)
Здравствуйте, Kolesiki, Вы писали:

K>Если код выглядит правильно, а работает — неправильно, ткнуть в него носом всех этих Липпертов и как в школе: "Переписывай заново, двоечник!".


Тут не переписывать надо, а ворнинг в компилятор добавить. default не имеет особого смысла для object-а, так как default без параметров — это указание компилятору вывести тип из использования. А вывод object бесполезен.

Ну, и с наследством этим кривым — Equals-ом на object-ах надо давно покончить было. Еще в 2.0 нужно было ввести кроме него еще и обобщенную реализацию вызывающую EqualityComparer<T>.Default.Equals(T, T). Тогда бы она предпочитается компилятором, при разрешении перегрузки и тип бы успешно выводился.

Еще имеет смысл запретить оператор == для ссылочных типов в которых он не определен. Для них == вызывает проверку равенства ссылок, что так же может привести к багам. Человек явно должен указывать, что хочет получить ссылочную эквавалентность, а не логическое равенство. Приводи к object или используй object.ReferenceEquals().
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Минутка WTF-20: Меньше кода - меньше ошибок
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.11.17 16:56
Оценка:
Здравствуйте, vasmann, Вы писали:

V>Equals(value, default) — означает вызывать метод Equals c первым параметром value и вторым "по умолчанию" для типа второго аргумента. Т.е Equals(object, object) будет вызван как Equals(value, default(object))


В этом "сценарии" нет смысла. И компилятор должен был бы об этом предупредить. Весь смысл данной темы, что подобные ошибки фиг заметишь в коде. Это грабли о которых надо знать. C++ way (tm)
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Минутка WTF-20: Меньше кода - меньше ошибок
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 09.11.17 22:41
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Еще имеет смысл запретить оператор == для ссылочных типов в которых он не определен. Для них == вызывает проверку равенства ссылок, что так же может привести к багам. Человек явно должен указывать, что хочет получить ссылочную эквавалентность, а не логическое равенство. Приводи к object или используй object.ReferenceEquals().


Да уж точно. Замена 100500 проверок на null в коде на ReferenceEquals — это прекрасная идея. В Nemerle как, запретил уже?
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[4]: Минутка WTF-20: Меньше кода - меньше ошибок
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.11.17 13:56
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Да уж точно. Замена 100500 проверок на null в коде на ReferenceEquals — это прекрасная идея. В Nemerle как, запретил уже?


А причем тут проверка на null? С ней, как раз, никаких проблем нет. Ну, кроме того, что в 90% случаев — это бойлерплэйт-код, который приходится писать из-за убогости языков. null — это специальный литерал. Второй операнд у "х != null" можно автоматом к object приводить.

Речь идет о сравнении двух объектов. Если у них еще к тому же переопределены GetHashcode и Equals — это почти наверняка ошибка. Если это делается намеренно, то лучше это явно указать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Отредактировано 10.11.2017 14:49 VladD2 . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.