RAD 10.4 - my sample Create and Using Generics of various Type include calling External app (Notepad) do show resulted and close it in 3 seconds
scenary:
scenary:
- MSWindows 10 Enterprise 64bits in VirtualBox VM (with 3GB + 2 vCPU)
- RAD Studio 10.4 SADness (9797) full installed
- Console 32bits project
[SHOWTOGROUPS=4,20]
[/SHOWTOGROUPS]
Code:
program prjCON_Generics_Constructor_to_Integer_Type;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.Classes,
System.SysUtils,
Winapi.Windows,
Winapi.Messages,
ShellApi,
VCL.Dialogs;
type
// TData = record
// Value: Integer;
// end;
TSomeClass<T: constructor> = class
class var
FValue: T;
function GetGeneric: T;
constructor Create;
end;
//
TMyGroup = class
private
FName : string;
FValue: string;
function GetFValue: string;
procedure SetFValue(const Value: string);
published
property name : string read FName write FName;
property somevalue: string read GetFValue write SetFValue;
public
constructor Create;
destructor Destroy;
end;
constructor TSomeClass<T>.Create;
begin
inherited Create;
FValue := T.Create; // constructor default because <T:Constructor> definition above!
end;
function TSomeClass<T>.GetGeneric: T;
begin
Result := FValue;
end;
{ TMyGroup }
constructor TMyGroup.Create;
begin
inherited Create;
end;
destructor TMyGroup.Destroy;
begin
inherited Destroy;
end;
function TMyGroup.GetFValue: string;
begin
Result := FValue;
end;
procedure TMyGroup.SetFValue(const Value: string);
begin
if not(FValue = Value) then
FValue := Value;
end;
// --------------------------------------------
var
someClassT1: TSomeClass<Integer>;
someClassT2: TSomeClass<string>;
someClassT3: TSomeClass<Double>;
someClassT4: TSomeClass<TDateTime>;
someClassT5: TSomeClass<TMyGroup>;
//
i : Integer;
lClassName : string;
lMyFileOutPut : TextFile;
lWinExecReturn : Cardinal;
lMyFindWindowReturn: HWND;
lPostMessageReturn : LongBool;
procedure prcWaitMeSeeTheResulted(lCommandLineAndParam: PAnsiChar; lFindWindowText: PWideChar);
begin
// ShellExecute(0, nil, 'MyFileOutPut.txt', nil, nil, SW_SHOWNORMAL);
//
lWinExecReturn := WinExec(lCommandLineAndParam, SW_SHOW);
// ShowMessage('let me see it'); // more easy :)
//
if (lWinExecReturn > 0) then
Sleep(10000); // thread main in wait mode...
//
lMyFindWindowReturn := FindWindow(nil, lFindWindowText);
//
if (lMyFindWindowReturn > 0) then
lPostMessageReturn := PostMessage(lMyFindWindowReturn, WM_CLOSE, 0, 0);
//
// if (lMyFindWindowReturn > 0) then
// BringWindowToTop(lMyFindWindowReturn);
end;
begin
//
ReportMemoryLeaksOnShutdown := true;
//
AssignFile(lMyFileOutPut, 'MyFileOutPut.txt');
Rewrite(lMyFileOutPut);
//
try
try
someClassT1 := TSomeClass<Integer>.Create;
someClassT1.FValue := 1234;
i := someClassT1.GetGeneric;
WriteLn(lMyFileOutPut, 'my i value: ', i);
//
someClassT2 := TSomeClass<string>.Create;
someClassT2.FValue := '-1234-';
i := StrToIntDef(someClassT2.GetGeneric, -9);
WriteLn(lMyFileOutPut, 'my i value: ', i);
//
someClassT3 := TSomeClass<Double>.Create;
someClassT3.FValue := 5.1234;
{ Round() = see TRoundingMode modes / exception = EInvalidOp = out limits }
i := Round(someClassT3.GetGeneric);
WriteLn(lMyFileOutPut, 'my i value: ', i);
//
someClassT4 := TSomeClass<TDateTime>.Create;
someClassT4.FValue := now;
i := Round(someClassT4.GetGeneric);
WriteLn(lMyFileOutPut, 'my i value: ', i);
//
someClassT5 := TSomeClass<TMyGroup>.Create;
someClassT5.FValue.name := 'Hello World';
//
someClassT5.FValue.somevalue := someClassT1.ClassName;
WriteLn(lMyFileOutPut, 'my i value: ', i, ' ', someClassT5.FValue.name, ' ', someClassT5.FValue.somevalue);
//
someClassT5.FValue.somevalue := someClassT2.ClassName;
WriteLn(lMyFileOutPut, 'my i value: ', i, ' ', someClassT5.FValue.name, ' ', someClassT5.FValue.somevalue);
//
someClassT5.FValue.somevalue := someClassT3.ClassName;
WriteLn(lMyFileOutPut, 'my i value: ', i, ' ', someClassT5.FValue.name, ' ', someClassT5.FValue.somevalue);
//
someClassT5.FValue.somevalue := someClassT4.ClassName;
WriteLn(lMyFileOutPut, 'my i value: ', i, ' ', someClassT5.FValue.name, ' ', someClassT5.FValue.somevalue);
//
someClassT5.FValue.somevalue := someClassT5.ClassName;
WriteLn(lMyFileOutPut, 'my i value: ', i, ' ', someClassT5.FValue.name, ' ', someClassT5.FValue.somevalue);
//
// causing the AV ... :))) i'm bad-guy!
//
someClassT1.FValue := StrtoInt('a1234');
i := someClassT1.GetGeneric;
WriteLn(lMyFileOutPut, 'my i value: ', i);
//
except
on E: Exception do
WriteLn(lMyFileOutPut, E.ClassName, ': ', E.Message);
end;
finally
CloseFile(lMyFileOutPut);
//
if not(someClassT5.FValue = nil) then // free my TGroup class if necessary to avoid leak memory
begin
someClassT5.FValue.Free;
//
ShowMessage('Free my someClassT5.FValue = TGroup created');
end;
//
if FileExists('MyFileOutPut.txt') then
prcWaitMeSeeTheResulted( { }
'notepad.exe MyFileOutPut.txt', { app.exe param }
'MyFileOutPut.txt - Bloco de Notas' { filename.ext - Notepad }
);
//
end;
end.
Last edited: