|
Гуру-тест для программистов 1С по C#, на сообразительность. | ☑ | ||
---|---|---|---|---|
0
Гений 1С
гуру
15.01.21
✎
13:13
|
Итак, нужен рефакторинг кода.
Есть много кода, вида: if (cond1) { struct_A r; r.field1 = "aга"; r.field2 = false; } else if (cond2) { struct_B r; r.field1 = "aга"; r.field2 = false; } else { struct_C r; r.field1 = "aга" + "мухоха"; //иногда код отличается для некоторых структур r.field2 = false; } Я придумал в итоге, как сделать красиво. Жду ваших гипотез. ООП (классы) не применял - из тушки по воробьям, считаю. Макросы нельзя в c#, увы. Но есть одно хитрое решение! ;-) |
|||
1
ДенисЧ
15.01.21
✎
13:15
|
||||
2
jbond
15.01.21
✎
13:18
|
(0) - твой код воняет сишкой.
Я никогда не видел на проде код шарпа со struct. |
|||
3
acht
15.01.21
✎
13:19
|
(0) Как там компонента поживает, гуру?
|
|||
4
acht
15.01.21
✎
13:19
|
И с чего ты взял, что это красиво?
|
|||
5
ДенисЧ
15.01.21
✎
13:20
|
(2) А с record видел?
|
|||
6
Гений 1С
гуру
15.01.21
✎
13:20
|
(1) неа, проще.
(2) это код китайских "братьев по разуму". (3) близится к завершению, видишь, "делюсь опытом" в этом гуру-тесте. |
|||
7
Гений 1С
гуру
15.01.21
✎
13:20
|
(4) Вот как ответ дам, поймете что красиво.
|
|||
8
acht
15.01.21
✎
13:22
|
(7) Лучше не надо
|
|||
9
Гений 1С
гуру
15.01.21
✎
13:23
|
(8) не ссы
|
|||
10
Кирпич
15.01.21
✎
13:29
|
(2) ну открой книжку какую нибудь и посмотри
|
|||
11
Garykom
гуру
15.01.21
✎
13:35
|
(0)
struct_ABC r; if (cond1) { r.field1 = "aга"; r.field2 = false; } else if (cond2) { r.field1 = "aга"; r.field2 = false; } else { r.field1 = "aга" + "мухоха"; //иногда код отличается для некоторых структур r.field2 = false; } |
|||
12
jbond
15.01.21
✎
13:36
|
(10) class используется в 24 раза чаще, чем struct:
https://github.com/search?l=C%23&q=%22public+class%22&type=Code https://github.com/search?l=C%23&q=%22public+class%22&type=Code И посмотри на кейсы struct - interoperability c Си-шным API |
|||
13
Кирпич
15.01.21
✎
13:36
|
(12) да пофиг
|
|||
14
Ненавижу 1С
гуру
15.01.21
✎
13:42
|
(12) странные показатели
ну ладно, а ничего что все Int32, Float, Boolean это struct? Но вообще вы еще сравните int и string, например, и сделайте выводы. |
|||
15
Garikk
15.01.21
✎
13:43
|
(0) struct_A - у них есть общий класс с этими field12? устанавливать поля приводя все это к нему, и не нужно плодить одно и тоже, в начала в if выбирать только правильный тип
== далее...а обхявление переменной внутри блока, а это так можно? это вообще имеет смысл? |
|||
16
Ненавижу 1С
гуру
15.01.21
✎
13:43
|
(5) мне не понравился их дизайн, вопрос есть: https://qna.habr.com/q/920331?e=10636635
|
|||
17
Garikk
15.01.21
✎
13:44
|
(15) это я к тому что приведенный пример кода с такими объявлениями бессмысленен
|
|||
18
Ненавижу 1С
гуру
15.01.21
✎
13:44
|
(15) "обхявление переменной внутри блока" это нормально вполне
|
|||
19
Garikk
15.01.21
✎
13:45
|
(18) а её будет видно вне блока?
|
|||
20
Ненавижу 1С
гуру
15.01.21
✎
13:45
|
(0) сделать единый интерфейс
|
|||
21
Ненавижу 1С
гуру
15.01.21
✎
13:45
|
(19) нет естественно
|
|||
22
Garikk
15.01.21
✎
13:46
|
(21) ну вот я о чем и говорю, код в примере не имеет смысла из-за такого
|
|||
23
Ненавижу 1С
гуру
15.01.21
✎
13:48
|
(22) я думаю это условность
но если, например, все эти "field1" являются свойствами, а в их get/set нетривиальная логика, то может быть оно и имеет выход наружу |
|||
24
Garikk
15.01.21
✎
13:49
|
(23) тогда смысла нет на мисте обсуждать такие вопросы
|
|||
25
Ненавижу 1С
гуру
15.01.21
✎
13:52
|
(24) это же гений
|
|||
26
Гений 1С
гуру
15.01.21
✎
13:55
|
(24) ну почему же, 1с-ники это все же программисты, большинство Си щупали за вымя
|
|||
27
Garikk
15.01.21
✎
13:57
|
(26) потому что надо кучу доп.вопросов задавать (на которые ответов я так и не увидел кстати) по реализации такого
одноэсники не умеют в ООП в большинствве, а здесь яркий пример такого кода p.s. а про Си, ты явно переоцениваешь людей тут ;)) |
|||
28
Ненавижу 1С
гуру
15.01.21
✎
13:57
|
(26) а причем тут си и шарп? или опять буквоед?
|
|||
29
jbond
15.01.21
✎
13:59
|
(26) - Гений, ты опять спутал си и си шарп
|
|||
30
Гений 1С
гуру
15.01.21
✎
14:01
|
(28) (29) кое в чем они похожи, не букводествуй
|
|||
31
jbond
15.01.21
✎
14:01
|
(14) Do not define a structure unless the type has all of the following characteristics:
- It logically represents a single value, similar to primitive types (integer, double, and so on). - It has an instance size smaller than 16 bytes. - It is immutable. - It will not have to be boxed frequently. https://stackoverflow.com/a/6973171 |
|||
32
Генератор
15.01.21
✎
14:03
|
Если в условиях просто сравнивается одна переменная с чем-то, можно диспетчеризацию по ключу. Сделать ассоц массив с ключами а в значениях анонимные функции (если в языке есть такие) а потом просто по ключу вызывать нужную.
|
|||
33
Генератор
15.01.21
✎
14:05
|
Или паттерн стратегия, тогда эта портянка условий кочует в фабрику, которая создает нужную стратегию, а потом эту стратегию из фабрики получаем и вызываем (у всех стратегий один интерфейс)
|
|||
34
Гений 1С
гуру
15.01.21
✎
14:06
|
(33) Это уже ООП
(32) думал на этот счет. Сперва конвертор структуры в универальную структуру и наоборот |
|||
35
Конструктор1С
15.01.21
✎
14:09
|
(0) девочка может уехать из деревни, но деревня из девочки не уедет никогда. А из тебя никогда не уедет 1с. Не позорься
|
|||
36
Генератор
15.01.21
✎
14:13
|
Вот посмотри, может подойдет https://ru.wikipedia.org/wiki/Мультиметод#C
|
|||
37
Гений 1С
гуру
15.01.21
✎
14:21
|
Ну, короче можно сделать через object, но что-то там тоже не все удобно, короче я решил забить.
Вот ход мысли - все структуры загоняем в одну r: object r; if (DevTypeFlagCheck(0x7f000000) == (int)AnvizNew.CustomType.DEV_TYPE_FLAG_CARDNO_BYTE_7) r = new AnvizNew.CCHEX_EMPLOYEE2UNICODE_INFO_CARDID_7_STRU(); else r = new AnvizNew.CCHEX_RET_PERSON_INFO_STRU(); Если надо получить/установить значение поля, вызываем метод типа: stru_field(r, "PersonID", _PersonID); Ну и сама мякотка - реализация: private object _stru_field(AnvizNew.CCHEX_RET_PERSON_INFO_STRU r, string field, object value) { return null; } private object _stru_field(AnvizNew.CCHEX_EMPLOYEE2UNICODE_INFO_CARDID_7_STRU r, string field, object value) { return null; } private object stru_field(object _r, string field, object value = null) { switch (_r) { case AnvizNew.CCHEX_RET_PERSON_INFO_STRU r: return _stru_field(r, field, value); case AnvizNew.CCHEX_EMPLOYEE2UNICODE_INFO_CARDID_7_STRU r: return _stru_field(r, field, value); } return null; } |
|||
38
Гений 1С
гуру
15.01.21
✎
14:22
|
В общем, на выходе получается проще сделать класс-обертку, или копи-пастить. Я решил копи-пастить, как у китайских друзей.
|
|||
39
Ненавижу 1С
гуру
15.01.21
✎
14:39
|
(37) ты скажи пробовал?
|
|||
40
Serginio1
15.01.21
✎
14:41
|
(38) Проще сделать классами и интерфейсы.
Проще скопипастить на классы с интерфейсом. Проблема структур это боксинг. https://habr.com/ru/post/239219/ https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/types/boxing-and-unboxing Ну и это относится и к интерфейсам. |
|||
41
Ненавижу 1С
гуру
15.01.21
✎
14:43
|
(38) полиморфизм вручную?
причем если появится новый тип надо будет во все case лезть расширять |
|||
42
Arbuz
15.01.21
✎
15:07
|
(30) Дык, оно и на 1С похоже тогда, точкой с запятой в конце строки оператора.
(34) Это не ООП, это функциональщина. (37) т.е. объявы внутри блока ты заменил на объект с неоднозначной структурой? И при большом количестве кейсов портянка кода та же, только в другом месте. Как это поддерживать? (41) Guru-practice. Гениально, чо. |
|||
43
Ненавижу 1С
гуру
15.01.21
✎
15:16
|
срочно статью на habr
|
|||
44
dmpl
15.01.21
✎
15:16
|
(37) Тебе за строки чтоли платят? Больше же строк. Красиво - это когда парой строк все решается, а остальное оно само.
|
|||
45
Гений 1С
гуру
15.01.21
✎
15:18
|
(42) портянка будет только в одном месте, буквально перечень объектов.
|
|||
46
Гений 1С
гуру
15.01.21
✎
15:18
|
(39) что пробовал? пробовал, работает
|
|||
47
NWsFF
15.01.21
✎
15:26
|
Это точно уровень гуру? Рефакторнуть кусок повторяющегося кода в функцию или класс использовать ее вместо много кода?
|
|||
48
Гений 1С
гуру
15.01.21
✎
15:29
|
(47) там список классов только в одной функции перечисляется, йо?
Object-обертка короче. |
|||
49
ejikbeznojek
15.01.21
✎
15:31
|
(37) Я думаю, что ты в 1С это уже проходил, а на # это ещё впереди.
Когда ты сначала доволен как ты решил проблему, с помощью костыля. А потом спустя год, когда что-то нужно подправить, понимаешь что нужно было делать по другому)) |
|||
50
NWsFF
15.01.21
✎
15:39
|
(48) не обертка а базовый класс причем при присваивании происходит unboxing , короче превращается в класс который как из пушки по воробьям как ты считаешь
|
|||
51
Гений 1С
гуру
15.01.21
✎
15:40
|
(50) да, да, я понимаю как это сделать на объектах, но ну его в баню.
|
|||
52
Ненавижу 1С
гуру
15.01.21
✎
16:01
|
(51) в общем не осилил, нормальный вариант обернуть в класс и вызывать виртуальный метод будет не больше строк
|
|||
53
jbond
15.01.21
✎
16:06
|
(14) бурная реакция на (31) как бе намекает, что здесь много спецов по английскому.
Перевожу на русский: структуры в шарпе используются для передачи параметров во внешние неуправляемые (unmanaged) модули, имеющие Сишный интерфейс. |
|||
54
Ненавижу 1С
гуру
15.01.21
✎
16:08
|
(53) ну хорошо, что из того следует?
|
|||
55
Ненавижу 1С
гуру
15.01.21
✎
16:14
|
(53) ты так написал, что ТОЛЬКО для этого и используются
|
|||
56
Кирпич
15.01.21
✎
16:37
|
(53) Кому не лень, могут и в гугле перевести. Вы с гением не в одной палате лежите случайно?
|
|||
57
jbond
15.01.21
✎
16:49
|
(55) - такого мнения мелкософт.
У них же написано: Не используйте struct, кроме специальных случаев ... |
|||
58
Serginio1
15.01.21
✎
17:31
|
(57) struct удобны и для скорости и для уменьшения нагрузки на сборщик мусора.
После того как добавили ref return и ref struct Скорость выполнения приближается к С++ https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/builtin-types/struct#ref-struct https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/ref-returns https://docs.microsoft.com/ru-ru/dotnet/api/system.span-1?view=net-5.0 |
|||
59
Serginio1
15.01.21
✎
17:33
|
||||
60
ДедМорроз
15.01.21
✎
21:27
|
А зачем вообще рефакторить это ?
Если объекты разные и должны быть разными,то создавать в конструкторе. |
|||
61
ДедМорроз
15.01.21
✎
21:43
|
Ну и в Си++ структура - это класс,у которого все поля public.
То есть,на самом деле,особой разницы нет. Но в компиллируемых языках расточивание методов происходит в момент компилляции. |
|||
62
Serginio1
15.01.21
✎
22:47
|
(61) В С++ разницы практически нет. Структура это класс на стеке.
В .Net ограничения на структуру в том, что нет наследования. Любое приведение к object это боксинг и унбоксинг. Интерфейсы для структур только с боксингом. https://blogs.u2u.be/u2u/post/c-value-type-boxing-by-interfaces В свое время были эксперименты по размещению классов на стеке https://xoofx.com/blog/2015/10/08/stackalloc-for-class-with-roslyn-and-coreclr/ Но дальше не пошли |
|||
63
Кирпич
16.01.21
✎
06:41
|
(62) "Структура это класс на стеке." Вы совсем там трёхнулись на свом ООП? Структура это просто структура. Какая разница, на стеке она или ёё из кучи выделили.
|
|||
64
Ненавижу 1С
гуру
16.01.21
✎
07:16
|
(61) а причем здесь C++?
(63) в производительности, когда приведете к интерфейсу - она уедет в кучу, потом вернется обратно |
|||
65
Ненавижу 1С
гуру
16.01.21
✎
07:18
|
(63) ну и в семантике, например, присваивания
|
|||
66
Serginio1
16.01.21
✎
13:07
|
(63) Ну не правильно высказался. В С++ разницы между классом и структурой нет. Класс может как на стеке так и в памяти.
В C# структура только на стеке или как поле класса. А класс не может создаваться на стеке. Так понятно? Структуры нужны для скорости и уменьшения нагрузки на GC. В приведенном примере https://xoofx.com/blog/2015/10/08/stackalloc-for-class-with-roslyn-and-coreclr/ есть разница The stack version will run in 400 ms with 0 GC collect The heap version will run in 5000 ms with 100+ GC collect Например в Java нет структур и много мест где производительность проседает с большим количеством классов (массивы), по сравнению с value типами Меньше нагрузка на GC. И память выделяется одним огромным куском. |
|||
67
Кирпич
16.01.21
✎
14:08
|
(66) "В C# структура только на стеке или как поле класса."
С какого перепугу только на стеке? Я могу описать структуру и создавать её с помощью new. Разве нет?
|
|||
68
Кирпич
16.01.21
✎
14:12
|
Можно и так и так
|
|||
69
Ненавижу 1С
гуру
16.01.21
✎
14:16
|
(67) (68) подучись перед тем как писать такое. new само по себе не значит, что в куче
|
|||
70
Кирпич
16.01.21
✎
14:18
|
(69) А что же оно значит?
|
|||
71
Ненавижу 1С
гуру
16.01.21
✎
14:31
|
(70) оно для вызовов конструкторов
кстати, для структур .net поддерживает (в отличие от c#) конструкторы без параметров но скорее всего в (68) описано одно и тоже |
|||
72
Кирпич
16.01.21
✎
14:34
|
(71) А конструкторы где память выделяют? Не на стеке же ёптыть.
|
|||
73
Ненавижу 1С
гуру
16.01.21
✎
14:45
|
(72) а почему они ее выделяют?
Кстати: struct A { public int x; } A a1 = new A(); Console.WriteLine(a1.x); //ок A a2; Console.WriteLine(a2.x); //не ок |
|||
74
Кирпич
16.01.21
✎
14:51
|
(73) " Console.WriteLine(a2.x);//не ок"
Ну это примудрости C#. Он не дает печатать мусор из стека. Присвой значение a2.x и прокатит |
|||
75
Кирпич
16.01.21
✎
14:53
|
(73) "а почему они ее выделяют?"
Ну как бы под объект то надо выделить память, если он реально создается |
|||
76
Кирпич
16.01.21
✎
14:58
|
+(74) В C# стековые надо инициализировать. Даже такое не прокатит
|
|||
77
Ненавижу 1С
гуру
16.01.21
✎
14:58
|
(75) она уже выделена статически, как и под любую переменную
int x = 42; это тоже структура и тоже на стеке |
|||
78
Кирпич
16.01.21
✎
14:59
|
(77) Вот ты x инициализировал. А структуру не инициализировал. Потому и ругается.
|
|||
79
Ненавижу 1С
гуру
16.01.21
✎
15:01
|
(78) я про то, что локальные переменные типа структуры (value object) живут на стеке
|
|||
80
Кирпич
16.01.21
✎
15:03
|
(79) Если просто объявить, без new, то на стеке. Иначе будут в куче. Как я и писал в (68).
|
|||
81
Ненавижу 1С
гуру
16.01.21
✎
15:06
|
(80) продолжай в это верить
|
|||
82
Кирпич
16.01.21
✎
15:08
|
(81) А как по другому? Как правильно?
|
|||
83
Кирпич
16.01.21
✎
15:11
|
Структуры в C# всегда выделяются на стеке? Это же глупо и смешно.
|
|||
84
Ненавижу 1С
гуру
16.01.21
✎
15:12
|
(83) не всегда, как члены класса - живут в куче
|
|||
85
Serginio1
16.01.21
✎
15:13
|
(67) https://docs.microsoft.com/ru-ru/dotnet/standard/design-guidelines/choosing-between-class-and-struct
Первое различие между ссылочными типами и типами значений будет рассмотрено в том, что ссылочные типы выделяются в куче и уничтожаются сборщиком мусора, тогда как типы значений выделяются либо в стеке, либо в виде встроенных строк, содержащих типы, и освобождаются при освобождении стека или при освобождении содержащего их типа. Таким образом, выделение и освобождение типов значений являются общими дешевле, чем выделение и освобождение ссылочных типов. new для value типов это инициализатор https://stackoverflow.com/questions/203695/does-using-new-on-a-struct-allocate-it-on-the-heap-or-stack структуры не могут быть в памяти, только в качестве объекта боксинг. то есть var box= (object)( new A()); для конструкторов value типов применяется несколько инциализаторов в заваисмости где память выделяется newobj: Выделяет значение в стеке, вызывает параметризованный конструктор. Используется для промежуточных значений, например для присвоения полю или использования в качестве аргумента метода. call instance: Использует уже выделенное место хранения (будь то в стеке или нет). Это используется в приведенном выше коде для назначения локальной переменной. Если одной и той же локальной переменной присваивается значение несколько раз с помощью нескольких newвызовов, она просто инициализирует данные поверх старого значения - она не выделяет больше пространства стека каждый раз. initobj: Использует уже выделенное место хранения и просто стирает данные. Это используется для всех наших вызовов конструктора без параметров, включая те, которые присваиваются локальной переменной. Для вызова метода эффективно вводится промежуточная локальная переменная ,и ее значение стираетсяinitobj. |
|||
86
Кирпич
16.01.21
✎
15:17
|
(85) Ну так могут структуры выделятся в куче или нет?
|
|||
87
Serginio1
16.01.21
✎
15:18
|
(85) >> для конструкторов value типов применяется несколько инциализаторов в заваисмости где память выделяется
Вернее выделение памяти на стеке и инциализация передаваемыми параметрами или обнуление памяти |
|||
88
Serginio1
16.01.21
✎
15:19
|
(86) Как структуры нет, как объект да. Но это уже отбоксенные структры приведенные к object
|
|||
89
Serginio1
16.01.21
✎
15:20
|
88+ я уже ссылки давал. Это азы
https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/types/boxing-and-unboxing |
|||
90
Кирпич
16.01.21
✎
15:21
|
(88) Не один ли хрен отбоксенные они или нет. Они структуры и они не на стеке.
|
|||
91
Serginio1
16.01.21
✎
15:25
|
(90) Большая. Это уже объект. У него есть поле со ссылкой на type (vmt).
По сути это уже другой тип, просто он приводится к value типу автоматически. |
|||
92
Serginio1
16.01.21
✎
15:29
|
91 верее не автоматически а явное привидение (int) .
Автоматически он к боксенному объекту приводится |
|||
93
Кирпич
16.01.21
✎
15:31
|
(91) А по мне так никакой разницы. Мне пофигу что там .NET внутри с моей структурой тварит. Пускай пакует во что хочет. Я пишу через точку и всё. А она в куче.
|
|||
94
Serginio1
16.01.21
✎
15:44
|
(93) Тебе пофигу. В Java тоже так посчитали. Но у них int и боксенный Integer
https://habr.com/ru/post/104231/ Так, заменив один int на Integer, можно сэкономить около 40% используемой памяти. Value типы нужны прежде всего для скорости при уменьшении нагрузки на сборщик мусора. Все зависит от количества таких объектов. Выбор между классом и структурой https://docs.microsoft.com/ru-ru/dotnet/standard/design-guidelines/choosing-between-class-and-struct Если тебя скорость не интересует. То идеальным выбором конечно будет класс. Про боксинг. Нужно не забывать отбоксить. interface IBankAccount { void Add(int amount); } struct BankAccount : IBankAccount { int value; public BankAccount(int value) => this.value = value; void IBankAccount.Add(int amount) => value += amount; public void Add(int amount) => value += amount; public void Print() => Console.WriteLine($"Value: {value}"); } BankAccount ba = new BankAccount(100); ba.Add(50); ba.Print(); IBankAccount iba = ba; iba.Add(50); ba.Print(); This piece of code will probably not print out what you might expect... The output is as follows: Value: 150 Value: 150 Нужно обратно скопировать данные ba=(BankAccount)iba; ba.Print(); тогда получим 200 |
|||
95
Ненавижу 1С
гуру
16.01.21
✎
16:18
|
Интересно автор поста вкуривает разницу между struct и class в c# и c++?
|
|||
96
Кирпич
16.01.21
✎
16:22
|
(94) Да я не собираюсь нигде структуры использовать. Я на C# не пишу пока.
Интересно, а как такая фигня работает? Получается, в xxx() автоматом боксится в объект и возвращает ссылку на него.
|
|||
97
Ненавижу 1С
гуру
16.01.21
✎
16:34
|
(96) так нельзя:
static ref XXX xxx() { XXX r; return ref r; } Нельзя передать ссылку на локальную переменную за пределы ее существования |
|||
98
Кирпич
16.01.21
✎
16:36
|
(97) Мне можно. У меня работает.
|
|||
99
Serginio1
16.01.21
✎
16:44
|
(96) Нет не боксится. Это аналог ref return и параметров передаваемых через out ref in
https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/builtin-types/struct#ref-struct Начиная с C# 7.2 в объявлении типа структуры можно использовать модификатор ref. Экземпляры типа структуры ref выделяются в стеке и не могут временно перейти в управляемую кучу. Для этого компилятор ограничивает использование типов структуры ref следующим образом: Структура ref не может быть типом элемента массива. Структура ref не может быть объявленным типом поля класса или структурой, отличной отref. Структура ref не может реализовывать интерфейсы. Структура ref не может быть упакована в System.ValueType или System.Object. Структура ref не может быть аргументом типа. Переменная структуры ref не может быть зафиксирована лямбда-выражением или локальной функцией. Переменную структуры ref нельзя использовать в методе async. Однако переменные структуры ref можно использовать в синхронных методах, например в тех, которые возвращают Task или Task<TResult>. Переменную структуры ref нельзя использовать в итераторах. |
|||
100
Serginio1
16.01.21
✎
16:45
|
||||
101
Serginio1
16.01.21
✎
16:46
|
||||
102
Serginio1
16.01.21
✎
16:48
|
Ну и передача параметров по ссылке in,ref,out
https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/in-parameter-modifier |
|||
103
Ненавижу 1С
гуру
16.01.21
✎
16:49
|
(98) Ошибка CS8168 Невозможно вернуть по ссылке локальный "r", так как это не локальная переменная ref ConsoleApp10 C:\Users\User\source\repos\ConsoleApp10\ConsoleApp10\Program.cs 15
|
|||
104
Кирпич
16.01.21
✎
16:54
|
(102) Так а как можно вернуть ссылку на стековую переменную. Это же глюк. Получается боксится
|
|||
105
Кирпич
16.01.21
✎
16:54
|
(103) Чота не правильно написал наверное
|
|||
106
Кирпич
16.01.21
✎
16:55
|
или С# старый
|
|||
107
Ненавижу 1С
гуру
16.01.21
✎
16:57
|
(105) я копировал, а не писал. Шарп новый
|
|||
108
Serginio1
16.01.21
✎
16:58
|
(103) ref struct только для .Net Standard 2.1 .То есть только для Core. Для .Net Framework не доступен.
|
|||
109
Serginio1
16.01.21
✎
16:59
|
||||
110
Кирпич
16.01.21
✎
17:00
|
(103) Извини, братан. Я просто здесь пробую. Хрен знает чо там за C# Ж))
https://www.onlinegdb.com/online_csharp_compiler |
|||
111
Кирпич
16.01.21
✎
17:04
|
(108) Так ссылка на что здесь возвращается? На стековую переменную или таки создается копия этой переменной в куче и уже на нее возвращется ссылка?
|
|||
112
Кирпич
16.01.21
✎
17:04
|
А ну щас несколько раз вызову
|
|||
113
Serginio1
16.01.21
✎
17:07
|
(111) А как ты думаешь? Что такое передача по ссылке?
ref, out, in Method(ref int param); Для проверки присвой разным переменным и измени |
|||
114
Serginio1
16.01.21
✎
17:08
|
и посмотри какое значение в реальном объекте
|
|||
115
Ненавижу 1С
гуру
16.01.21
✎
17:09
|
(110) это не настоящий: Mono 5.10.1.20 (tarball Thu Mar 29 10:48:35 UTC 2018)
|
|||
116
Кирпич
16.01.21
✎
17:10
|
(115) Ааааа. Так может это просто баг у них такой
|
|||
117
Кирпич
16.01.21
✎
17:12
|
(114) Я знаю что такое по ссылке. Меня смущает, что ссылка на стековую переменную, которая станет мусором при выходе из xxx()
|
|||
118
Serginio1
16.01.21
✎
17:12
|
(115) Попробуй на .Net 5
|
|||
119
Ненавижу 1С
гуру
16.01.21
✎
17:16
|
(118) я и попробовал на нем:
static ref XXX xxx() { XXX r; return ref r; //<<вот так нельзя локальную переменную вернуть CS8168 } |
|||
120
Кирпич
16.01.21
✎
17:18
|
Интересно это баг в Mono или у них там реально боксит
|
|||
121
Serginio1
16.01.21
✎
18:03
|
https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/ref-returns
Для классса прокатывает public class TestRef { int i; public ref int RefProperty { get { return ref i; } } public ref int GetRefProperty() { return ref i; } } Для struct чеhез Span public ref struct TestRefStruct { int i; //var array = new byte[100]; Span<byte> arraySpan;// = new Span<byte>(array); public ref byte RefProperty { get { return ref arraySpan[0]; } } } или расширения https://overcoder.net/q/495043/почему-метод-структуры-c-не-может-вернуть-ссылку-на-поле-а-метод-не-являющийся |
|||
122
Serginio1
16.01.21
✎
18:13
|
Из комментариев
Документация» ( github.com/dotnet/csharplang/blob/master/proposals/csharp-7.2/… ) гласит, что «поля структуры экземпляра безопасны для возврата до тех пор, пока получатель безопасен для возврата». Здесь приёмник (параметр foo ) безопасен для возврата (потому что in ), поэтому, кажется, работает как задумано. В то время как первый случай покрыт "this", небезопасно возвращаться из членов структуры ". |
|||
123
Кирпич
17.01.21
✎
08:48
|
Можно структуру в массив запихнуть.
Получается почти как в Mono
|
|||
124
Гений 1С
гуру
17.01.21
✎
09:08
|
Все бы решилось если бы в C# были бы генераторы статического кода, то бишь макросы, как в Си, было бы намного красивее и без извращений:
MULTICOND Cond1 {struct_A r;} Cond2 {struct_B r;}) GENERAL { r.field1 = "aга"; r.field2 = false; } |
|||
125
Кирпич
17.01.21
✎
09:15
|
(124) А почему нельзя просто функцию написать и копипастить её вызов?
|
|||
126
Ненавижу 1С
гуру
17.01.21
✎
10:37
|
(124) макросы это зло
Генераторы кода есть |
|||
127
Гений 1С
гуру
17.01.21
✎
10:46
|
(126) зло не зло, а тут красивее через генераторы кода (макросы).
(125) потому что типы разные. |
|||
128
Ненавижу 1С
гуру
17.01.21
✎
10:53
|
(127) правильнее через интерфейсы
|
|||
129
Конструктор1С
17.01.21
✎
10:53
|
||||
130
Конструктор1С
17.01.21
✎
10:55
|
||||
131
Ненавижу 1С
гуру
17.01.21
✎
10:57
|
(127) нужна статья про кризис-айти в виде отсутствия макросов в шарпе
|
|||
132
Кирпич
17.01.21
✎
11:02
|
(127) "типы разные"
ну ты тип как параметр тоже используй |
|||
133
Гений 1С
гуру
17.01.21
✎
11:09
|
(132) нельзя, язык не поддерживает
|
|||
134
Ненавижу 1С
гуру
17.01.21
✎
11:11
|
(133) передавать как параметр так себе идея. Но тип Type там есть из коробки
Рано тебе ещё гуру-тесты создавать |
|||
135
Гений 1С
гуру
17.01.21
✎
11:12
|
(134) и как Type поможет?
|
|||
136
Ненавижу 1С
гуру
17.01.21
✎
11:14
|
(135) тебе никак. Забудь. Я кстати за адаптер и интерфейс, а не интроспекцию
|
|||
137
Гений 1С
гуру
17.01.21
✎
11:18
|
(136) вот видишь, макрос проще решает эту проблему
|
|||
138
Кирпич
17.01.21
✎
11:27
|
(137) покажи макрос для С++, который решит такую задачу
|
|||
139
Ненавижу 1С
гуру
17.01.21
✎
11:30
|
(137) не вижу. Костыли это
|
|||
140
Serginio1
17.01.21
✎
11:37
|
(123) Да только XXX[] x = { new XXX() }; это уже объект. Не то
(124) Ты не поверишь, но уже есть Introducing C# Source Generators https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/ https://blog.jetbrains.com/dotnet/2020/11/12/source-generators-in-net-5-with-resharper/ https://github.com/dotnet/roslyn/blob/master/docs/features/source-generators.md |
|||
141
Кирпич
17.01.21
✎
11:39
|
(140) Массив объект? Ну наверное. А структура в массиве не объект же?
|
|||
142
Ненавижу 1С
гуру
17.01.21
✎
11:42
|
(141) массив это точно объект. Класс Array
Структура нет. Мне интересно подсчет таких ссылок тоже используется, чтобы объект раньше времени не финализировался? |
|||
143
Кирпич
17.01.21
✎
11:43
|
Так вот еще можно |
|||
144
Ненавижу 1С
гуру
17.01.21
✎
11:47
|
(143) ты уже проверяешь на тру-компиляторе?
|
|||
145
Кирпич
17.01.21
✎
11:48
|
(144) ага
|
|||
146
Serginio1
17.01.21
✎
11:53
|
(143) new XXX[1] это массив. Он выделяется в куче. С этим проблем нет.
Проблема в структурах выделяемых на стеке. При этом ref держит ссылку которая уже не валидная, из-за перезаписи стека. С объектами такой проблемы нет ибо за объектом следит GC и корректирует ссылки |
|||
147
Serginio1
17.01.21
✎
11:54
|
(141) Суть в том, что если структура в объекте, то она не на стеке! Смотри 146
|
|||
148
Кирпич
17.01.21
✎
11:55
|
(146) Ну как бы это понятно. Я просто показал пример, как создать в куче структуру и получить на неё ссылку.
|
|||
149
Ненавижу 1С
гуру
17.01.21
✎
11:58
|
(147) вопрос. Какая гарантия что объект не уничтожится, если есть ref ссылка на его поле-структуру?
Надо углубиться в то как выглядит внутри ref. |
|||
150
Serginio1
17.01.21
✎
12:12
|
(149)
https://overcoder.net/q/495043/почему-метод-структуры-c-не-может-вернуть-ссылку-на-поле-а-метод-не-являющийся Из комментариев Документация» ( github.com/dotnet/csharplang/blob/master/proposals/csharp-7.2/… ) гласит, что «поля структуры экземпляра безопасны для возврата до тех пор, пока получатель безопасен для возврата». Здесь приёмник (параметр foo ) безопасен для возврата (потому что in ), поэтому, кажется, работает как задумано. В то время как первый случай покрыт "this", небезопасно возвращаться из членов структуры ". |
|||
151
Serginio1
17.01.21
✎
12:15
|
150 То есть через расширения мы можежем вернуть ссылку на член структуры
struct Foo { internal int _x; public ref readonly int MemberGetX() => ref _x; // ^^^ // Error CS8170: Struct members cannot return 'this' or other instance members by reference } Это приводит к ошибке. Члены CS8170 Struct не могут возвращать "этот" или другие члены экземпляра по ссылке. Тем не менее, выполнение одной и той же функции с использованием метода расширения не вызывает ошибки: static class FooExtensions { public static ref readonly int ExtensionGetX( this in Foo foo ) { return ref foo._x; } } var f = new Foo(); Console.WriteLine( f.X ); f.GetXRefExtension() = 123; Console.WriteLine( f.X ); // You can also do it without using an extension method, but the caller is required to specify ref: FooExtensions.GetXRef( ref f ) = 999; Console.WriteLine( f.X ); /* Output: * 0 * 123 * 999 */ То есть виден контекст и ref работает только на вызывающем стеке |
|||
152
Serginio1
17.01.21
✎
14:19
|
140 + обсуждение и примеры
Introducing C# Source Generators http://rsdn.org/forum/dotnet/7719189.flat |
|||
153
PR
17.01.21
✎
21:32
|
Природа очистилась настолько, что с первой страницы ушли почти все темы Гени
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |