Opérateurs de classe Delphi "Explicit" et "Implicit"
DLZ.Delphi
Messages postés1Date d'inscriptiondimanche 12 novembre 2023StatutMembreDernière intervention12 novembre 2023
-
12 nov. 2023 à 19:41
Bonjour,
Pourriez-vous l'erreur que je commets dans l'utilisation des opérateurs de classe "Explicit" et "Implicit".
En effet, dans le code suivant, le compilateur Delphi 11.3 ne prend pas en compte les opérateurs définis dans le record helper
unit uPasswordPolicy;
interface
uses
System.IniFiles, // For the type "TIniFile"
System.SysUtils; // For the type "Exception"
type
TUpperAsciiChar = 'A'..'Z';
TLowerAsciiChar = 'a'..'z';
TNumericChar = '0'..'9';
TSymbolChar1 = '!'..'/';
TSymbolChar2 = ':'..'@';
TSymbolChar3 = '['..'`';
TSymbolChar4 = '{'..'~';
TCharacterKind = (ckUppercase, ckLowercase, ckNumeric, ckSymbol);
TCharKindSet = set of TCharacterKind;
ECharacterKind = Exception;
type
TPasswordPolicy = packed record
strict private var
fLifeTime : Cardinal; // Number of days alive
FMinChars : Cardinal; // Minimum number of characaters
fRequired : TCharKindSet; // Required character kinds
strict private const
cLifeTime = 'Password''s Lifetime in day(s)';
cMinChars = 'Minimum nuber of characters for password';
cRequired = 'Types of characters required in password';
DefaultLifetime : Cardinal = 90;
DefaultMinChars : Cardinal = 10;
DefaultRequired : TCharKindSet = [ckUppercase, ckLowercase, ckNumeric, ckSymbol];
public
constructor Create ( const aVoid : Pointer );
procedure ReadFromIniFile ( const aIniFile : TCustomIniFile;
const aSection : string );
procedure WriteToIniFile ( const aIniFile : TCustomIniFile;
const aSection : string );
public
property LifeTime : Cardinal read fLifeTime;
property MinChars : Cardinal read fMinChars;
property Required : TCharKindSet read fRequired;
end;
{██████████████████████████████████████████████████████████████████████████████}
implementation
uses
System.Classes; // For the type "TStringList"
{══════════════════════════════════════════════════════════════════════════════}
{ TCharKindSetHelper Class }
{______________________________________________________________________________}
type
TCharKindSetHelper = record Helper for TCharKindSet
strict private const
ValueNames : array[TCharacterKind] of string = ('Uppercase', 'Lowercase', 'Numeric', 'Symbol');
strict private
class function CharKind( aValue : string ) : TCharacterKind; static;
public
class operator Explicit( aValue : string ) : TCharKindSet;
class operator Implicit( aValue : string ) : TCharKindSet;
class operator Explicit( aValue : TCharKindSet ) : string;
class operator Implicit( aValue : TCharKindSet ) : string;
end;
{______________________________________________________________________________}
class function TCharKindSetHelper.CharKind( aValue : string ) : TCharacterKind;
begin
for Result := Low(Result) to High(Result) do
if( SameText(ValueNames[Result], aValue) ) then
Exit;
raise ECharacterKind.CreateFmt( '"%s" is not a kind of characters !', [aValue] );
end;
{‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾}
{______________________________________________________________________________}
class operator TCharKindSetHelper.Explicit( aValue : string ) : TCharKindSet;
var lValueList : TArray<string>;
begin
{ }
{ ─Clear the result set }
{ ──────────────────── }
Result := [];
{ }
{ ─Split the value to an array of strings }
{ ────────────────────────────────────── }
lValueList := aValue.Split( [','] );
{ }
{ ─Analyze each substring }
{ ────────────────────── }
for var lValue in lValueList do
Result := Result + [CharKind(lValue)];
{ Rq: An exception occurs if one substring is not an enumeration value ! }
end;
{‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾}
{______________________________________________________________________________}
class operator TCharKindSetHelper.Implicit( aValue : string ) : TCharKindSet;
var lValueList : TArray<string>;
begin
{ }
{ ─Clear the result set }
{ ──────────────────── }
Result := [];
{ }
{ ─Split the value to an array of strings }
{ ────────────────────────────────────── }
lValueList := aValue.Split( [','] );
{ }
{ ─Analyze each substring }
{ ────────────────────── }
for var lValue in lValueList do
Result := Result + [CharKind(lValue)];
{ Rq: An exception occurs if one substring is not an enumeration value ! }
end;
{‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾}
{______________________________________________________________________________}
class operator TCharKindSetHelper.Explicit( aValue : TCharKindSet ) : string;
var lStrings : TStringList;
begin
lStrings := TStringList.Create();
try
{ }
{ ─Append the name of each existing CharacterKind enum }
{ ─────────────────────────────────────────────────── }
for var lKind := Low(TCharacterKind) to High(TCharacterKind) do
if( lKind in aValue ) then
lStrings.Append( ValueNames[lKind] );
{ }
{ ─Return the text list build }
{ ────────────────────────── }
Result := lStrings.CommaText;
finally
lStrings.Free;
end;
end;
{‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾}
{______________________________________________________________________________}
class operator TCharKindSetHelper.Implicit( aValue : TCharKindSet ) : string;
var lStrings : TStringList;
begin
lStrings := TStringList.Create();
try
{ }
{ ─Append the name of each existing CharacterKind enum }
{ ─────────────────────────────────────────────────── }
for var lKind := Low(TCharacterKind) to High(TCharacterKind) do
if( lKind in aValue ) then
lStrings.Append( ValueNames[lKind] );
{ }
{ ─Return the text list build }
{ ────────────────────────── }
Result := lStrings.CommaText;
finally
lStrings.Free;
end;
end;
{‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾}
{ TCharKindSetHelper Class }
{══════════════════════════════════════════════════════════════════════════════}
{══════════════════════════════════════════════════════════════════════════════}
{ TPasswordPolicy Class }
{______________________________________________________________________________}
{ Rq: Compiler requires unnecessary argument for record constructor }
constructor TPasswordPolicy.Create( const aVoid : Pointer );
begin
fLifeTime := DefaultLifetime;
FMinChars := DefaultMinChars;
fRequired := DefaultRequired;
end;
{‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾}
{______________________________________________________________________________}
procedure TPasswordPolicy.ReadFromIniFile( const aIniFile : TCustomIniFile;
const aSection : string );
begin
fLifeTime := aIniFile.ReadInt64 ( aSection, cLifeTime, DefaultLifetime );
FMinChars := aIniFile.ReadInt64 ( aSection, cMinChars, DefaultMinChars );
fRequired := aIniFile.ReadString( aSection, cRequired, DefaultRequired );
end;
{‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾}
{______________________________________________________________________________}
procedure TPasswordPolicy.WriteToIniFile( const aIniFile : TCustomIniFile;
const aSection : string );
begin
aIniFile.WriteInt64 ( aSection, cLifeTime, fLifeTime );
aIniFile.WriteInt64 ( aSection, cMinChars, fMinChars );
aIniFile.WriteString( aSection, cRequired, fRequired );
var lReqStr : string := string(fRequired);
end;
{‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾}
{ TPasswordPolicy Class }
{══════════════════════════════════════════════════════════════════════════════}
END.
Par ailleurs, existe-t-il un moyen pour ne pas dupliquer le code des opérateurs Explicit et Implicit équivalents ?
Merci pour votre aide.
Didier
A voir également:
Delphi pos
Public static implicit operator - Meilleures réponses