На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
! Друзья, соблюдайте, пожалуйста, правила форума и данного раздела:
Данный раздел не предназначен для вопросов и обсуждений, он содержит FAQ-заготовки для разных языков программирования. Любой желающий может разместить здесь свою статью. Вопросы же задавайте в тематических разделах!
• Если ваша статья может быть перенесена в FAQ соответствующего раздела, при условии, что она будет оформлена в соответствии с Требованиями к оформлению статей.
• Чтобы остальным было проще понять, указывайте в описании темы (подзаголовке) название языка в [квадратных скобках]!
Модераторы: Модераторы
  
> In-place создание массива из констант/переменных, [Delphi] В основном, для организации цикла
    In-place создание массива из констант

    Этот метод мне подсказал, кажется, leo, за что ему респект.

    Задача:
    Иногда бывает нужно сделать перебор ряда однотипных переменных. Самый распространенный пример - массовое управление группами контролов
    ExpandedWrap disabled
      Button1.Enabled := False;
      Button3.Enabled := False;
      Button5.Enabled := False;


    Лично мой взор неуемного оптимизатора сия конструкция оскорбляет, но на первый взгляд от нее никуда не деться - разве что чере временный массив, но и его придется заполнять по одному. Конструкция [item1, item2, ...] работает только в параметрах подпрограмм - ну а создавать отдельную процедуру для одного действия тоже не хочется.
    К счастью, есть и другой, хитрый способ получить переменную дин. массива, а именно:
    ExpandedWrap disabled
      <dyn_array_type>.Create(item1, item2, ...)


    Для нашего случая:
    ExpandedWrap disabled
      var
        btn: TButton;
      ...
        for btn in TArray<TButton>.Create(Button2, Button6, Button7) do
          btn.Enabled := False;

    либо получаем для неоднократного последующего применения
    ExpandedWrap disabled
      var
        i: Integer;
        BtnGroup1: TArray<TButton>;
      ...
        BtnGroup1 := TArray<TButton>.Create(Button2, Button6, Button7);
        ...
        for i := Low(BtnGroup1) to High(BtnGroup1) do
         BtnGroup1[i].Enabled := False;

    А можно и для разношерстных контролов
    ExpandedWrap disabled
      var
        comp: TControl;
      ...
        for comp in TArray<TControl>.Create(Button2, Button6, CheckBox3) do
          comp.Enabled := False;


    Работает и без generics, но тип дин. массива обязательно должен быть предварительно объявлен:
    ExpandedWrap disabled
      type
        TArrayButton = array of TButton;
      var
        btn: TButton;
      ...
        for btn in TArrayButton.Create(Button1, Button2) do
          btn.Enabled := False;
    Codero ergo sum
    // Программирую — значит, существую
      Цитата
      Лично мой взор неуемного оптимизатора
      стесняюсь спросить, а что тут оптимизировано?
        SPM, куча однотипных действий выполняется не копипастой, а циклом, как и положено однотипным действиям. Оптимизация скорее на уровне исходника, чем машинного кода.

        Добавлено
        Хорошо пригодится в случае, когда, например, надо управлять доступностью групп контролов на основе уровня юзера.
        Codero ergo sum
        // Программирую — значит, существую
          Цитата Fr0sT @
          Работает и без generics, но тип дин. массива обязательно должен быть предварительно объявлен

          Можно же использовать Open array parameters...
            Цитата Filka @
            Можно же использовать Open array parameters...

            Как оно применимо к данной ситуации?
            Codero ergo sum
            // Программирую — значит, существую
              Например, так:
              ExpandedWrap disabled
                procedure SetEnabledBtn(const BtnArr: array of TButton; Value: Boolean);
                var
                  I: Integer;
                begin
                  for I := Low(BtnArr) to High(BtnArr) do
                    BtnArr[I].Enabled := Value;
                end;
                 
                procedure TForm1.Button1Click(Sender: TObject);
                begin
                  SetEnabledBtn([Button2, Button3, Button4], False);
                end;
              Сообщение отредактировано: Filka -
                Filka, отдельная процедура занимает больше места, чем объявление типа). К тому же что, если понадобится менять не только enabled, а, например, еще и visible?
                Codero ergo sum
                // Программирую — значит, существую
                  Цитата Fr0sT @
                  отдельная процедура занимает больше места, чем объявление типа
                  И что?

                  Цитата Fr0sT @
                  если понадобится менять не только enabled, а, например, еще и visible?
                  В процедуре и менять...

                  Зато Open array parameters есть в любой версии Delphi...
                  Сообщение отредактировано: Filka -
                    Filka, я ж и не спорю, что решить задачу можно несколькими способами. Просто делюсь более неочевидным.
                    Codero ergo sum
                    // Программирую — значит, существую
                      Я тоже не спорю. Я просто хотел сказать, что подобное можно сделать и в старых версиях Delphi.
                        Вариант без generics тоже, возможно, сработает - мне не на чем проверить.
                        Codero ergo sum
                        // Программирую — значит, существую
                          Цитата Fr0sT @
                          К тому же что, если понадобится менять не только enabled, а, например, еще и visible?
                          Цитата Fr0sT @
                          В процедуре и менять...
                          Зато Open array parameters есть в любой версии Delphi...

                          Ну можно еще использовать универсальную функцию просто для создания и инициализации массива контролов в рамках подхода Fr0sT
                          ExpandedWrap disabled
                            type
                              TCtlArray = array of TControl;
                            function GetCtlArray(Controls:array of TControl):TCtlArray;
                            begin
                              SetLength(Result,High(Controls)+1);
                              Move(Controls[0],Result[0],SizeOf(TControl)*(High(Controls)+1));
                            end;
                            Цитата Fr0sT @
                            Вариант без generics тоже, возможно, сработает - мне не на чем проверить.

                            Например, в D7 не сработает, т.к. там нет конструкторов у дин. массивов.
                            Сообщение отредактировано: Filka -
                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                            0 пользователей:


                            Рейтинг@Mail.ru
                            [ Script Execution time: 0,1348 ]   [ 17 queries used ]   [ Generated: 18.07.18, 05:04 GMT ]