Opérateurs de classe Delphi "Explicit" et "Implicit"

DLZ.Delphi Messages postés 1 Date d'inscription dimanche 12 novembre 2023 Statut Membre Dernière intervention 12 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:
Rejoignez-nous