Для расовых ненавистников "with"
Коим я являюсь (ненавистником with)
Добрые люди предложили замену:
(procedure (A: TObject)
begin
A.Free;
end)(TObject.Create);
Добрые люди предложили замену:
Задача: осуществить перебор строковых значений в исходной строке, разделённых символом-разделителем, с учётом символа-кавычки.
Решение:
unit dnStringIterator; interface type TStringValuesIterator = record type TCallBack = reference to procedure (const AValue: string); TOptions = set of (ioTrimValues, ioDequoteValues); private FSourceString: string; FDelimiter, FQuoteChar: Char; FCheckQuotes: Boolean; FOptions: TOptions; FOffset, FLength: Integer; FCurrent: string; public constructor Init(const ASourceString: string; ADelimiter: Char; AQuoteChar: Char = #0; AOptions: TOptions = []); function GetEnumerator: TStringValuesIterator; function MoveNext: Boolean; procedure Run(ACallBack: TCallBack); inline; property Current: string read FCurrent; end; implementation uses SysUtils; { TStringValuesIterator } constructor TStringValuesIterator.Init(const ASourceString: string; ADelimiter, AQuoteChar: Char; AOptions: TOptions); begin FSourceString := ASourceString; FDelimiter := ADelimiter; FQuoteChar := AQuoteChar; FOffset := 1; FLength := Length(FSourceString); FOptions := AOptions; FCurrent := ''; FCheckQuotes := FQuoteChar <> #0; // нельзя, чтобы символ разделитель совпадал с символом-кавычкой: Assert(not FCheckQuotes or (FDelimiter <> FQuoteChar)); // нельзя использовать ioDeqouteValues, если не указан QuoteChar Assert(FCheckQuotes or not (ioDequoteValues in FOptions)); end; function TStringValuesIterator.GetEnumerator: TStringValuesIterator; begin Result := Self; end; function TStringValuesIterator.MoveNext: Boolean; var IsInQuote: Boolean; CurPos: Integer; Ch: Char; begin Result := (FLength > 0) and (FOffsetПримеры использования
С явным объявлением дополнительной переменной:var svi: TStringValuesIterator; begin svi.Init(TestString, ','); while svi.MoveNext do Memo1.Lines.Add(svi.Current); end;Без явного объявления дополнительной переменной, используя with:
begin with TStringValuesIterator.Init(TestString, ',') do while MoveNext do Memo1.Lines.Add(Current); end;Используя анонимную процедуру:
begin TStringValuesIterator.Init(TestString, ',').Run( procedure (const AValue: string) begin Memo1.Lines.Add(AValue); end ); end;Используя for-in синтаксис:
var Tmp: string; begin for Tmp in TStringValuesIterator.Init(TestString, ',') do Memo1.Lines.Add(Tmp); end;