Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум на Исходниках.RU > Все языки: Статьи, заготовки в FAQ > In-place создание массива из констант/переменных |
Автор: Fr0sT 27.11.13, 12:05 |
In-place создание массива из констант Этот метод мне подсказал, кажется, leo, за что ему респект. Задача: Иногда бывает нужно сделать перебор ряда однотипных переменных. Самый распространенный пример - массовое управление группами контролов <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> Button1.Enabled := False; Button3.Enabled := False; Button5.Enabled := False; Лично мой взор неуемного оптимизатора сия конструкция оскорбляет, но на первый взгляд от нее никуда не деться - разве что чере временный массив, но и его придется заполнять по одному. Конструкция [item1, item2, ...] работает только в параметрах подпрограмм - ну а создавать отдельную процедуру для одного действия тоже не хочется. К счастью, есть и другой, хитрый способ получить переменную дин. массива, а именно: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> <dyn_array_type>.Create(item1, item2, ...) Для нашего случая: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> var btn: TButton; ... for btn in TArray<TButton>.Create(Button2, Button6, Button7) do btn.Enabled := False; либо получаем для неоднократного последующего применения <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> 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; А можно и для разношерстных контролов <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> var comp: TControl; ... for comp in TArray<TControl>.Create(Button2, Button6, CheckBox3) do comp.Enabled := False; Работает и без generics, но тип дин. массива обязательно должен быть предварительно объявлен: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> type TArrayButton = array of TButton; var btn: TButton; ... for btn in TArrayButton.Create(Button1, Button2) do btn.Enabled := False; |
Автор: SPM 27.11.13, 18:11 |
Цитата стесняюсь спросить, а что тут оптимизировано? Лично мой взор неуемного оптимизатора |
Автор: Fr0sT 28.11.13, 06:10 |
SPM, куча однотипных действий выполняется не копипастой, а циклом, как и положено однотипным действиям. Оптимизация скорее на уровне исходника, чем машинного кода. Добавлено Хорошо пригодится в случае, когда, например, надо управлять доступностью групп контролов на основе уровня юзера. |
Автор: Filka 23.12.13, 05:22 |
Цитата Fr0sT @ Работает и без generics, но тип дин. массива обязательно должен быть предварительно объявлен Можно же использовать Open array parameters... |
Автор: Fr0sT 23.12.13, 06:28 |
Как оно применимо к данной ситуации? |
Автор: Filka 23.12.13, 06:36 |
Например, так: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> 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; |
Автор: Fr0sT 23.12.13, 07:24 |
Filka, отдельная процедура занимает больше места, чем объявление типа). К тому же что, если понадобится менять не только enabled, а, например, еще и visible? |
Автор: Filka 23.12.13, 07:32 |
И что? В процедуре и менять... Зато Open array parameters есть в любой версии Delphi... |
Автор: Fr0sT 24.12.13, 06:30 |
Filka, я ж и не спорю, что решить задачу можно несколькими способами. Просто делюсь более неочевидным. |
Автор: Filka 24.12.13, 06:38 |
Я тоже не спорю. Я просто хотел сказать, что подобное можно сделать и в старых версиях Delphi. |
Автор: Fr0sT 24.12.13, 06:43 |
Вариант без generics тоже, возможно, сработает - мне не на чем проверить. |
Автор: leo 24.12.13, 06:44 |
Цитата Fr0sT @ К тому же что, если понадобится менять не только enabled, а, например, еще и visible? Ну можно еще использовать универсальную функцию просто для создания и инициализации массива контролов в рамках подхода Fr0sT <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> 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; |
Автор: Filka 24.12.13, 06:47 |
Например, в D7 не сработает, т.к. там нет конструкторов у дин. массивов. |