Вход | Регистрация
    1  2   

Гуру-тест для программистов 1С по C#, на сообразительность.

Гуру-тест для программистов 1С по C#, на сообразительность.
Я
   Гений 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
   jbond
 
2 - 15.01.21 - 13:18
(0) - твой код воняет сишкой.

Я никогда не видел на проде код шарпа со struct.
   acht
 
3 - 15.01.21 - 13:19
(0) Как там компонента поживает, гуру?
   acht
 
4 - 15.01.21 - 13:19
И с чего ты взял, что это красиво?
   ДенисЧ
 
5 - 15.01.21 - 13:20
(2) А с record видел?
   Гений 1С
 
6 - 15.01.21 - 13:20
(1) неа, проще.
(2) это код китайских "братьев по разуму".
(3) близится к завершению, видишь, "делюсь опытом" в этом гуру-тесте.
   Гений 1С
 
7 - 15.01.21 - 13:20
(4) Вот как ответ дам, поймете что красиво.
   acht
 
8 - 15.01.21 - 13:22
(7) Лучше не надо
   Гений 1С
 
9 - 15.01.21 - 13:23
(8) не ссы
   Кирпич
 
10 - 15.01.21 - 13:29
(2) ну открой книжку какую нибудь и посмотри
   Garykom
 
11 - 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;
}
   jbond
 
12 - 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) да пофиг
   Ненавижу 1С
 
14 - 15.01.21 - 13:42
(12) странные показатели
ну ладно, а ничего что все Int32, Float, Boolean это struct?

Но вообще вы еще сравните int и string, например, и  сделайте выводы.
   Garikk
 
15 - 15.01.21 - 13:43
(0) struct_A - у них есть общий класс с этими field12? устанавливать поля приводя все это к нему, и не нужно плодить одно и тоже, в начала в if выбирать только правильный тип
==

далее...а обхявление переменной внутри блока, а это так можно? это вообще имеет смысл?
   Ненавижу 1С
 
16 - 15.01.21 - 13:43
(5) мне не понравился их дизайн, вопрос есть: https://qna.habr.com/q/920331?e=10636635
   Garikk
 
17 - 15.01.21 - 13:44
(15) это я к тому что приведенный пример кода с такими объявлениями бессмысленен
   Ненавижу 1С
 
18 - 15.01.21 - 13:44
(15) "обхявление переменной внутри блока" это нормально вполне
   Garikk
 
19 - 15.01.21 - 13:45
(18) а её будет видно вне блока?
   Ненавижу 1С
 
20 - 15.01.21 - 13:45
(0) сделать единый интерфейс
   Ненавижу 1С
 
21 - 15.01.21 - 13:45
(19) нет естественно
   Garikk
 
22 - 15.01.21 - 13:46
(21) ну вот я о чем и говорю, код в примере не имеет смысла из-за такого
   Ненавижу 1С
 
23 - 15.01.21 - 13:48
(22) я думаю это условность

но если, например, все эти "field1" являются свойствами, а в их get/set нетривиальная логика, то может быть оно и имеет выход наружу
   Garikk
 
24 - 15.01.21 - 13:49
(23) тогда смысла нет на мисте обсуждать такие вопросы
   Ненавижу 1С
 
25 - 15.01.21 - 13:52
(24) это же гений
   Гений 1С
 
26 - 15.01.21 - 13:55
(24) ну почему же, 1с-ники это все же программисты, большинство Си щупали за вымя
   Garikk
 
27 - 15.01.21 - 13:57
(26) потому что надо кучу доп.вопросов задавать (на которые ответов я так и не увидел кстати) по реализации такого

одноэсники не умеют в ООП в большинствве, а здесь яркий пример такого кода

p.s. а про Си, ты явно переоцениваешь людей тут ;))
   Ненавижу 1С
 
28 - 15.01.21 - 13:57
(26) а причем тут си и шарп? или опять буквоед?
   jbond
 
29 - 15.01.21 - 13:59
(26) - Гений, ты опять спутал си и си шарп
   Гений 1С
 
30 - 15.01.21 - 14:01
(28) (29) кое в чем они похожи, не букводествуй
 
 Рекламное место пустует
   jbond
 
31 - 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
Или паттерн стратегия, тогда эта портянка условий кочует в фабрику, которая создает нужную стратегию, а потом эту стратегию из фабрики получаем и вызываем (у всех стратегий один интерфейс)
   Гений 1С
 
34 - 15.01.21 - 14:06
(33) Это уже ООП
(32) думал на этот счет. Сперва конвертор структуры в универальную структуру и наоборот
   Конструктор1С
 
35 - 15.01.21 - 14:09
(0) девочка может уехать из деревни, но деревня из девочки не уедет никогда. А из тебя никогда не уедет 1с. Не позорься
   Генератор
 
36 - 15.01.21 - 14:13
Вот посмотри, может подойдет https://ru.wikipedia.org/wiki/Мультиметод#C
   Гений 1С
 
37 - 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;
        }
   Гений 1С
 
38 - 15.01.21 - 14:22
В общем, на выходе получается проще сделать класс-обертку, или копи-пастить. Я решил копи-пастить, как у китайских друзей.
   Ненавижу 1С
 
39 - 15.01.21 - 14:39
(37) ты скажи пробовал?
   Serginio1
 
40 - 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

Ну и это относится и к интерфейсам.
   Ненавижу 1С
 
41 - 15.01.21 - 14:43
(38) полиморфизм вручную?
причем если появится новый тип надо будет во все case лезть расширять
   Arbuz
 
42 - 15.01.21 - 15:07
(30) Дык, оно и на 1С похоже тогда, точкой с запятой в конце строки оператора.
(34) Это не ООП, это функциональщина.
(37) т.е. объявы внутри блока ты заменил на объект с неоднозначной структурой? И при большом количестве кейсов портянка кода та же, только в другом месте. Как это поддерживать?
(41) Guru-practice.
Гениально, чо.
   Ненавижу 1С
 
43 - 15.01.21 - 15:16
срочно статью на habr
   dmpl
 
44 - 15.01.21 - 15:16
(37) Тебе за строки чтоли платят? Больше же строк. Красиво - это когда парой строк все решается, а остальное оно само.
   Гений 1С
 
45 - 15.01.21 - 15:18
(42) портянка будет только в одном месте, буквально перечень объектов.
   Гений 1С
 
46 - 15.01.21 - 15:18
(39) что пробовал? пробовал, работает
   NWsFF
 
47 - 15.01.21 - 15:26
Это точно уровень гуру? Рефакторнуть кусок повторяющегося кода в функцию или класс использовать ее вместо много кода?
   Гений 1С
 
48 - 15.01.21 - 15:29
(47) там список классов только в одной функции перечисляется, йо?
Object-обертка короче.
   ejikbeznojek
 
49 - 15.01.21 - 15:31
(37) Я думаю, что ты в 1С это уже проходил, а на # это ещё впереди.
Когда ты сначала доволен как ты решил проблему, с помощью костыля.
А потом спустя год, когда что-то нужно подправить, понимаешь что нужно было делать по другому))
   NWsFF
 
50 - 15.01.21 - 15:39
(48) не обертка а базовый класс причем при присваивании происходит unboxing , короче превращается в класс который как из пушки по воробьям как ты считаешь
   Гений 1С
 
51 - 15.01.21 - 15:40
(50) да, да, я понимаю как это сделать на объектах, но ну его в баню.
   Ненавижу 1С
 
52 - 15.01.21 - 16:01
(51) в общем не осилил, нормальный вариант обернуть в класс и вызывать виртуальный метод будет не больше строк
   jbond
 
53 - 15.01.21 - 16:06
(14) бурная реакция на (31) как бе намекает, что здесь много спецов по английскому.

Перевожу на русский: структуры в шарпе используются для передачи параметров во внешние неуправляемые (unmanaged) модули, имеющие Сишный интерфейс.
   Ненавижу 1С
 
54 - 15.01.21 - 16:08
(53) ну хорошо, что из того следует?
   Ненавижу 1С
 
55 - 15.01.21 - 16:14
(53) ты так написал, что ТОЛЬКО для этого и используются
   Кирпич
 
56 - 15.01.21 - 16:37
(53) Кому не лень, могут и в гугле перевести. Вы с гением не в одной палате лежите случайно?
   jbond
 
57 - 15.01.21 - 16:49
(55) - такого мнения мелкософт.

У них же написано: Не используйте struct, кроме специальных случаев ...
   Serginio1
 
58 - 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
   Serginio1
 
59 - 15.01.21 - 17:33
   ДедМорроз
 
60 - 15.01.21 - 21:27
А зачем вообще рефакторить это ?
Если объекты разные и должны быть разными,то создавать в конструкторе.
 
 Рекламное место пустует
   ДедМорроз
 
61 - 15.01.21 - 21:43
Ну и в Си++ структура - это класс,у которого все поля public.
То есть,на самом деле,особой разницы нет.
Но в компиллируемых языках расточивание методов происходит в момент компилляции.
   Serginio1
 
62 - 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) "Структура это класс на стеке." Вы совсем там трёхнулись на свом ООП? Структура это просто структура. Какая разница, на стеке она или ёё из кучи выделили.
   Ненавижу 1С
 
64 - 16.01.21 - 07:16
(61)  а причем здесь C++?
(63)  в производительности, когда приведете к интерфейсу - она уедет в кучу, потом вернется обратно
   Ненавижу 1С
 
65 - 16.01.21 - 07:18
(63) ну и в семантике, например, присваивания
   Serginio1
 
66 - 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. Разве нет?
using System;

public struct XXX {
        string x;
        bool y;
    }

class HelloWorld {
  static void Main() {
    var x1 = new XXX();
    var x2 = new XXX();
  }
}

   Кирпич
 
68 - 16.01.21 - 14:12
Можно и так и так
    var x1 = new XXX();//в куче

    XXX x2;            //на стеке, но не факт 

   Ненавижу 1С
 
69 - 16.01.21 - 14:16
(67) (68) подучись перед тем как писать такое. new само по себе не значит, что в куче
   Кирпич
 
70 - 16.01.21 - 14:18
(69) А что же оно значит?
   Ненавижу 1С
 
71 - 16.01.21 - 14:31
(70) оно для вызовов конструкторов
кстати, для структур .net поддерживает (в отличие от c#) конструкторы без параметров


но скорее всего в (68) описано одно и тоже
   Кирпич
 
72 - 16.01.21 - 14:34
(71) А конструкторы где память выделяют? Не на стеке же ёптыть.
   Ненавижу 1С
 
73 - 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# стековые надо инициализировать. Даже такое не прокатит
int x;
Console.WriteLine(x);

   Ненавижу 1С
 
77 - 16.01.21 - 14:58
(75) она уже выделена статически, как и под любую переменную
int x = 42;

это тоже структура и тоже на стеке
   Кирпич
 
78 - 16.01.21 - 14:59
(77) Вот ты x инициализировал. А структуру не инициализировал. Потому и ругается.
   Ненавижу 1С
 
79 - 16.01.21 - 15:01
(78) я про то, что локальные переменные типа структуры (value object) живут на стеке
   Кирпич
 
80 - 16.01.21 - 15:03
(79) Если просто объявить, без new, то на стеке. Иначе будут в куче. Как я и писал в (68).
   Ненавижу 1С
 
81 - 16.01.21 - 15:06
(80) продолжай в это верить
   Кирпич
 
82 - 16.01.21 - 15:08
(81) А как по другому? Как правильно?
   Кирпич
 
83 - 16.01.21 - 15:11
Структуры в C# всегда выделяются на стеке? Это же глупо и смешно.
   Ненавижу 1С
 
84 - 16.01.21 - 15:12
(83) не всегда, как члены класса - живут в куче
   Serginio1
 
85 - 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) Ну так могут структуры выделятся в куче или нет?
   Serginio1
 
87 - 16.01.21 - 15:18
(85) >> для конструкторов value типов применяется несколько инциализаторов в заваисмости где память выделяется
Вернее выделение памяти на стеке и инциализация передаваемыми параметрами или обнуление памяти
   Serginio1
 
88 - 16.01.21 - 15:19
(86) Как структуры нет, как объект да. Но это уже отбоксенные структры приведенные к object
   Serginio1
 
89 - 16.01.21 - 15:20
   Кирпич
 
90 - 16.01.21 - 15:21
(88) Не один ли хрен отбоксенные они или нет. Они структуры и они не на стеке.
   Serginio1
 
91 - 16.01.21 - 15:25
(90) Большая. Это уже объект. У него есть поле со ссылкой на type (vmt).
По сути это уже другой тип, просто он приводится к value типу автоматически.
   Serginio1
 
92 - 16.01.21 - 15:29
91 верее не автоматически а явное привидение (int) .
Автоматически он к боксенному объекту приводится
   Кирпич
 
93 - 16.01.21 - 15:31
(91) А по мне так никакой разницы. Мне пофигу что там .NET внутри с моей структурой тварит. Пускай пакует во что хочет. Я пишу через точку и всё. А она в куче.
   Serginio1
 
94 - 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
   Ненавижу 1С
 
95 - 16.01.21 - 16:18
Интересно автор поста вкуривает разницу между struct и class в c# и c++?
   Кирпич
 
96 - 16.01.21 - 16:22
(94) Да я не собираюсь нигде структуры использовать. Я на C# не пишу пока.
Интересно, а как такая фигня работает? Получается, в xxx() автоматом боксится в объект и возвращает ссылку на него.
public struct XXX {
   public int x;
   public int y;
}

class HelloWorld {
    
static ref XXX xxx() {
    XXX r;
    return ref r;
}
  static void Main() {
    ref XXX x1 = ref xxx();
    ref XXX x2 = ref x1;
    
    x1.x = 100500;
    
    Console.WriteLine(x2.x);
  }
}

   Ненавижу 1С
 
97 - 16.01.21 - 16:34
(96) так нельзя:
static ref XXX xxx() {
    XXX r;
    return ref r;
}

Нельзя передать ссылку на локальную переменную за пределы ее существования
   Кирпич
 
98 - 16.01.21 - 16:36
(97) Мне можно. У меня работает.
   Serginio1
 
99 - 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 нельзя использовать в итераторах.
   Serginio1
 
100 - 16.01.21 - 16:45
  1  2   

Список тем форума
Рекламное место пустует  Рекламное место пустует
Здесь во втором сообщении вам дадут решение, а в двадцатом дадут правильное решение. Ymryn
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.