Конвертировать массив в массив const в Delphi - PullRequest
0 голосов
/ 29 мая 2018

Я ищу простой и идеально общий (или использующий обобщенные) способ преобразования array в array of const (= array of TVarRec).В моем конкретном случае у меня есть array of Variant и я хочу передать его в функцию Format().

Это то, что я нашел до сих пор, но мне это кажется хакерским:

function MyFormat(const Fmt: string; const Args: TArray<Variant>): string;
var
  A: array of TVarRec;
  I: Integer;
begin
  SetLength(A, Length(Args));
  for I:= Low(Args) to High(Args) do begin
    A[I].VType:= vtVariant;
    A[I].VVariant:= @Args[I];
  end;
  Result:= Format(Fmt, A);
end;

Кажется, работает.Это безопасно?

Можно ли сделать это короче, лучше, быстрее или я могу вместо этого использовать что-нибудь готовое?:)


Просто некоторые дополнительные мысли и забавные факты:

System.Rtti.TValue недавно стал моим другом.Тем не менее, кажется, что здесь не хватает функции.Я могу прочитать свой массив, используя TValue.From(), но, похоже, нет способа вывести его как array of TVarRec.Есть замечательный TValueArrayToArrayOfConst, но он не очень помогает, потому что мне пришлось сначала создать array of TValue, который отличается от массива, хранящегося в одном TValue ...: (

По крайней мере TValue может выводить один элемент как TVarRec, поэтому я подумал, что смогу создать универсальный конвертер для всех типов массивов. Но ...

Как вы думаете, это работает?

for I:= Low(Args) to High(Args) do A[I]:= TValue.From(Args[I]).AsVarRec;

Он компилируется, но память TValue освобождается после использования, и, поскольку TVarRec.VVariant является указателем, он затем указывает на какое-то старое место, которое будет переопределено в следующем цикле.

1 Ответ

0 голосов
/ 29 мая 2018

Ваша функция безопасна и быстра.Он выделяет только небольшой массив памяти A[] и передает все значения по ссылке.Я не могу думать ни о чем быстрее - без преждевременной оптимизации.Я могу только сделать некоторый рефакторинг для повторного использования TArray<variant> в TArray<TVarRec> процедуру преобразования.

Использование TValue.From().AsVarRec будет определенно медленнее, если ваш ввод действительно TArray<Variant>.

Насчет TVarRec перелистывающих ссылок, вы правы: эти структуры - просто простые указатели в стеке без выделения, поэтому все упомянутые переменные должны быть доступны во время вызова функции.Поэтому, если вы используете TArray<TVarRec> локальное преобразование, вы должны убедиться, что TArray<variant> все еще выделяется при вызове функции format().

...