Než popíši další z nových možností u Delphi 2010, tak aby to majitelům starších Delphi nebylo líto odkáži je na podobnou opensource implementaci třídy TStopWatch - ale přijdete o několik zajímavých novinek. Tak ale zpět k současnosti - zároveň se bude jednat o pěkné jazykové konstrukce ohledně záznamu, včetně operátorů třídy - třeba Vás to bude inspirovat, mně osobně se to zamlouvá.
Delphi 2010 obsahuje unit Diagnostics.pas, který momentálně obsahuje jedinou třídu resp. rozšířený record s názvem TStopWatch, který mimochodem obsahuje pěkné použití rozšířeného recordu a class operatory.
type
TStopwatch = record
strict private const TicksPerMillisecond: Int64 = $2710;
strict private const TicksPerSecond: Int64 = $989680;
strict private class var TickFrequency: Double;
strict private
FElapsed: Int64;
FRunning: Boolean;
FStartTimeStamp: Int64;
function GetElapsed: TTimeSpan;
function GetElapsedDateTimeTicks: Int64;
function GetElapsedMilliseconds: Int64;
function GetElapsedTicks: Int64;
class procedure InitStopwatchType; static;
public
class function Create: TStopwatch; static;
class function GetTimeStamp: Int64; static;
procedure Reset;
procedure Start;
class function StartNew: TStopwatch; static;
procedure Stop;
property Elapsed: TTimeSpan read GetElapsed;
property ElapsedMilliseconds: Int64 read GetElapsedMilliseconds;
property ElapsedTicks: Int64 read GetElapsedTicks;
property IsRunning: Boolean read FRunning;
public class var Frequency: Int64;
public class var IsHighResolution: Boolean;
end;
Základem je velmi šikovný nový typ TTimeSpan definovaný v TimeSpan.pas.
type
TTimeSpan = record
// vynechány privátní a ne public pole
public const
TicksPerMillisecond = 10000;
TicksPerSecond = 1000 * Int64(TicksPerMillisecond);
TicksPerMinute = 60 * Int64(TicksPerSecond);
TicksPerHour = 60 * Int64(TicksPerMinute);
TicksPerDay = 24 * TIcksPerHour;
public
constructor Create(ATicks: Int64); overload;
constructor Create(Hours, Minutes, Seconds: Integer); overload;
constructor Create(Days, Hours, Minutes, Seconds: Integer); overload;
constructor Create(Days, Hours, Minutes, Seconds, Milliseconds: Integer); overload;
function Add(const TS: TTimeSpan): TTimeSpan; overload;
function Duration: TTimeSpan;
function Negate: TTimeSpan;
function Subtract(const TS: TTimeSpan): TTimeSpan; overload;
class function FromDays(Value: Double): TTimeSpan; static;
class function FromHours(Value: Double): TTimeSpan; static;
class function FromMinutes(Value: Double): TTimeSpan; static;
class function FromSeconds(Value: Double): TTimeSpan; static;
class function FromMilliseconds(Value: Double): TTimeSpan; static;
class function FromTicks(Value: Int64): TTimeSpan; static;
class function Parse(const S: string): TTimeSpan; static;
class function TryParse(const S: string; out Value: TTimeSpan): Boolean; static;
// class operatory
class operator Add(const Left, Right: TTimeSpan): TTimeSpan;
class operator Subtract(const Left, Right: TTimeSpan): TTimeSpan;
class operator Equal(const Left, Right: TTimeSpan): Boolean;
class operator NotEqual(const Left, Right: TTimeSpan): Boolean;
class operator GreaterThan(const Left, Right: TTimeSpan): Boolean;
class operator GreaterThanOrEqual(const Left, Right: TTimeSpan): Boolean;
class operator LessThan(const Left, Right: TTimeSpan): Boolean;
class operator LessThanOrEqual(const Left, Right: TTimeSpan): Boolean;
class operator Negative(const Value: TTimeSpan): TTimeSpan;
class operator Positive(const Value: TTimeSpan): TTimeSpan;
//!implicitni konverze na string
class operator Implicit(const Value: TTimeSpan): string;
class operator Explicit(const Value: TTimeSpan): string;
property Ticks: Int64 read FTicks;
property Days: Integer read GetDays;
property Hours: Integer read GetHours;
property Minutes: Integer read GetMinutes;
property Seconds: Integer read GetSeconds;
property Milliseconds: Integer read GetMilliseconds;
property TotalDays: Double read GetTotalDays;
property TotalHours: Double read GetTotalHours;
property TotalMinutes: Double read GetTotalMinutes;
property TotalSeconds: Double read GetTotalSeconds;
property TotalMilliseconds: Double read GetTotalMilliseconds;
class property MinValue: TTimeSpan read FMinValue;
class property MaxValue: TTimeSpan read FMaxValue;
class property Zero: TTimeSpan read FZero;
end;
Ale zpět k TStopWatch. Vytvoříme novou aplikaci, na formulář dáme tlačítko a TListBox. U tlačítka napíšeme uvedenou obsluhu.
implementation
uses
Diagnostics;
{$R *.dfm}
procedure TForm1.btn1Click(Sender: TObject);
var
sw:TStopWatch;
xIndex: Integer;
begin
sw.Reset;
sw.Start;
lst1.Clear;
for xIndex := 0 to 1000 - 1 do
lst1.Items.Add(IntToStr(Random(1000000)));
sw.Stop;
ShowMessage(sw.Elapsed); // poznámka níže
end;
Na řádku 17 se využije právě implicitní konverze na string, viz. class operator Implicit. Sčítání, odčítání atd. je realizováno dalšími operátory.
Ještě bych upozornil, že třída použije QueryPerformanceCounter pokud je volání dostupné, jinak použije klasicky GetTickCount (viz. IsHighResolution).