IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo

FAQ DelphiConsultez toutes les FAQ

Nombre d'auteurs : 124, nombre de questions : 934, dernière mise à jour : 23 octobre 2024  Ajouter une question

 

Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums Delphi et Delphi et bases de données de www.developpez.com et de l'expérience personnelle des auteurs.

Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose soient correctes. Les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous souhaitez y apporter des corrections ou la compléter, contactez un responsable (lien au bas de cette page).

Nous espérons que cette FAQ saura répondre à vos attentes. Nous vous en souhaitons une bonne lecture.

L'équipe Delphi de Developpez.com.

SommaireLangageLangage - Divers (10)
précédent sommaire suivant
 

L'instruction For Each permettant l'énumération d'une collection n'est pas disponible en Delphi Win32. Si dans la plupart des cas les collections sont indexables via un ordinal de 1 à Count, certaines ne le sont pas. Il est alors indispensable d'utiliser un énumérateur de collection.

Les collections disposent d'une méthode retournant un objet d'énumération transtypable en IEnumVariant. Cet objet dispose d'une méthode Next permettant d'extraire un certain nombre d'éléments de la collection. Next avance automatiquement dans la collection jusqu'à la fin. Il faut tester la valeur retournée par Next afin de savoir si la fin est atteinte.

La déclaration de IEnumVariant est la suivante :

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
IEnumVariant = interface(IUnknown) 
    ['{00020404-0000-0000-C000-000000000046}'] 
    function Next(celt: LongWord; var rgvar : OleVariant; 
      out pceltFetched: LongWord): HResult; stdcall; 
    function Skip(celt: LongWord): HResult; stdcall; 
    function Reset: HResult; stdcall; 
    function Clone(out Enum: IEnumVariant): HResult; stdcall; 
  end;
Le paramètre rgVar contenant l'item de collection en retour doit être de type OleVariant. Il doit être transtypé en élément de type IDispatch avant d'être transtypé en élément de base de la collection.

À titre d'exemple, le code suivant permet d'extraire la liste des langues de Word définies dans la collection Languages.
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Obtention de la liste des langues 
Langs:=Word.Languages; 
// On va utiliser l'énumérateur de collection fourni 
IEnum:=Langs._NewEnum as IEnumVariant; 
While IEnum.Next(1,Element,Nombre)=S_OK Do 
Begin 
  // Indispensable ici de passer par un IDisp intermédiaire... 
  IDisp := Element; 
  Langue := IDisp As Language; 
  // MAJ de la liste 
  With Liste.Items.Add Do 
  Begin 
    Caption := IntToStr(Langue.ID); 
    SubItems.Add(Langue.Name); 
    SubItems.Add(Langue.NameLocal); 
    If Langue.ActiveSpellingDictionary=Nil 
      Then SubItems.Add('Non') 
      Else SubItems.Add('Oui'); 
    If Langue.ActiveGrammarDictionary=Nil 
      Then SubItems.Add('Non') 
      Else SubItems.Add('Oui'); 
  End; 
End;
Une alternative au code précédent :
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
procedure WordlLangage;  
var Word  : Variant;  
    Element: OleVariant;  
  
    IEnum : IEnumVariant;  
    Langue : Variant;  
    Nombre : LongWord;  
begin  
  Word := CreateOleObject('Word.Application');  
  
   // Obtention de la liste des langues  
  IEnum:=IUnKnown(Word.Languages._NewEnum) as IEnumVariant;  
  
   // Puis utilisation de l'énumérateur de collection fourni  
  While IEnum.Next(1,Element,Nombre)=S_OK Do  
  Begin  
     // Il est indispensable de transtyper Element  
    Langue := IUnknown(Element) As Language;  
  
    Writeln(IntToStr(Langue.ID),' ',Langue.Name,' ',Langue.NameLocal);  
  End;  
  Word.Quit;  
  Word := unassigned;  
end;
Depuis sa version 2005, Delphi supporte, pour .NET et Win32, l'itération sur des éléments d'une collection (iteration over containers). Voir aussi.

Mis à jour le 20 janvier 2014 Laurent Dardenne Nono40

Afin de pouvoir appeler la méthode appropriée au moment souhaité, un objet doit s'appuyer sur une liste de ses méthodes virtuelles : la VMT ou Virtual Methods Table (Table des Méthodes Virtuelles). Cette table est mise en place par le constructeur d'un objet dans le cas où il déclare une méthode virtuelle.

Après l'appel du constructeur l'instance reçue est en fait un pointeur vers une zone mémoire qui contient d'abord l'adresse de la VMT de la classe, puis les adresses des champs de sa classe de base, stockées dans l'ordre de leur déclaration comme une suite contiguë de variables.
Les champs sont toujours alignés et correspondent à un type unpacked record. Tous les champs hérités d'une classe ancêtre sont stockés avant les nouveaux champs définis dans la classe descendante, la dernière adresse contient donc le dernier champ déclaré dans la classe.

Aux offsets positifs une VMT se compose d'une liste de pointeurs de méthodes, un par méthode virtuelle définie par l'utilisateur, dans l'ordre de déclaration du type de la classe.
Aux offsets négatifs, une VMT contient un certain nombre de champs utilisés en internes.

On peut donc dire que le type d'un objet est un pointeur sur la VMT.

Toute classe possède sa propre VMT, conservant toujours un lien avec la VMT de son ancêtre (hiérarchie de classe). Il y a donc une copie de la VMT chaque fois que vous héritez d'une classe.

La classe TObject déclare plusieurs méthodes et une propriété cachée pour stocker une référence à la classe de l'objet. Cette propriété contient un pointeur vers la VMT de la classe. Chaque classe a une VMT unique et tous les objets de cette classe partagent la VMT de la classe.
C'est-à-dire que l'héritage d'une classe à partir d'une autre implique l'héritage de la VMT complète de cette dernière, les nouvelles méthodes étant ajoutées en fin de table.
La VMT d'un objet contient toutes les méthodes virtuelles de ses ancêtres comme celles qu'il déclare, les méthodes virtuelles emploient donc plus de mémoire que des méthodes dynamiques, bien qu'elles s'exécutent plus rapidement.

Lorsqu'un appel à une méthode virtuelle est effectué, l'objet recherche dans sa VMT s'il trouve la méthode recherchée. Si c'est le cas, alors il utilise l'adresse enregistrée et exécute la méthode. Sinon, il parcourt la VMT de son ancêtre direct et ainsi de suite jusqu'à l'ancêtre le plus éloigné dans la hiérarchie.

De même, lorsqu'une méthode surchargée fait appel à la méthode ancêtre, une recherche est effectuée en partant cette fois-ci de la VMT du premier ancêtre.
Ceci est dû au fait qu'une méthode virtuelle est liée au moment de son exécution et pas au moment de la compilation.

La VMT est détruite par le destructeur lorsque celle-ci n'a plus lieu d'exister.

Une référence de classe est implémentée comme un pointeur vers la VMT de la classe.

Traduction d'un tableau extrait d'un article de Brian Long :

Offset Nom de constante Description
-76 vmtSelfPtr Adresse de la 1ère entrée de la VMT si elle existe sinon du nom de classe *
-72 vmtIntfTable Adresse de la table des interfaces implémentées *
-68 vmtAutoTable Adresse de la section des 'class automated' (Delphi 2) *
-64 vmtInitTable Adresse de la table des champs requérant une initialisation *
-60 vmtTypeInfo Adresse des informations RTTI *
-56 vmtFieldTable Adresse de la table des champs publiés (published) *
-52 vmtMethodTable Adresse de la table des méthodes publiées (published) *
-48 vmtDynamicTable Adresse de la DMT (table des méthodes dynamic) *
-44 vmtClassName Adresse du nom de classe, chaîne de caractères/string
-40 vmtInstanceSize Taille en octet d'une instance d'objet
-36 vmtParent .Adresse de la VMT de la classe ancêtre *
-32 vmtSafeCallException Adresse de la méthode virtuelle, SafeCallException *
-28 vmtAfterConstruction Adresse de la méthode virtuelle, AfterConstruction
-24 vmtBeforeDestruction Adresse de la méthode virtuelle, BeforeDestruction
-20 vmtDispatch Adresse de la méthode virtuelle, Dispatch
-16 vmtDefaultHandler Adresse de la méthode virtuelle, DefaultHandler
-12 vmtNewInstance Adresse de la méthode virtuelle, NewInstance
-8 vmtFreeInstance Adresse de la méthode virtuelle, FreeInstance
-4 vmtDestroy Adresse du destructeur virtuel, Destroy
Les entrées indiquées * sont à nil si elles ne sont pas renseignées. Cette disposition est compatible avec une v-table de C++ et avec COM.

La VMT contient l'adresse des méthodes virtuelles (déclarées avec la directive virtual ou override) mais elle n'inclut pas les adresses définies dans TObject (SafeCallException, AfterConstruction, BeforeDestruction, expédition, DefaultHandler, NewInstance, FreeInstance et le destructeur destroy) qui sont renseignées avant la VMT.

Au lieu d'employer la directive virtual, vous pouvez également employer la directive dynamic. La sémantique est identique, mais l'implémentation est différente. La recherche d'une méthode virtuelle dans une VMT est rapide car le compilateur génére un index directement dans la VMT.

Pour terminer sachez que la directive override remplace, dans la VMT, l'adresse originale de la méthode concernée par l'adresse de cette nouvelle méthode.

Voir aussi le source de l'unité System.

Puisque toutes les VMT doivent être stockées dans le même segment de données, les objets créés dans des DLL sont accompagnés de leur propre VMT mais elles sont stockées dans le segment de données de la DLL.

Mis à jour le 20 janvier 2014 Bestiol Eric Sigoillot Laurent Dardenne Mac LAK tourlourou

Les méthodes dynamiques sont fondamentalement des méthodes virtuelles mais avec un système de répartition (dispatching system) différent.
La différence est que la DMT (Dynamic Method Table ou Table dynamique de méthode) n'est pas complètement copiée à chaque fois que vous instanciez un objet.

Le compilateur affecte un nombre unique à chaque méthode dynamique et associe ces nombres avec des adresses de méthodes afin de construire un tableau dynamique de méthodes (DMT).
À la différence de la VMT, la DMT d'un objet contient seulement les méthodes dynamiques qu'il déclare, et cette méthode se fonde sur la DMT de son ancêtre pour le reste de ses méthodes dynamiques.
Cette approche fait que les DMT sont plus lentes que les VMT mais réduit leur occupation mémoire en évitant de recopier la VMT dans son intégralité à chaque fois que vous héritez d'un objet.

Elles prennent plus de temps lors de l'appel parce qu'il se peut que vous deviez parcourir les DMT de plusieurs ancêtres avant de trouver l'adresse d'une méthode dynamique particulière.
Quand une méthode dynamique est appelée elle est d'abord recherchée dans la DMT de l'objet lui-même. Si elle n'est pas trouvée elle est recherchée dans la DMT de son ancêtre direct et ainsi de suite.

L'utilisation de méthodes dynamiques ne prend son sens que dans quelques cas spéciaux (objets avec beaucoup de méthodes dynamiques/virtuelles, par exemple une centaine, et ayant de nombreux héritages).
En général vous devriez vous en tenir à l'utilisation de méthodes virtuelles.

Citation de Holger Lembke :
Les DMT (Dynamic Methods Table) sont en ceci différentes qu'elles ne référencent plus toutes les méthodes des ancêtres. La DMT est incluse dans la VMT (voir le champ "Adresse de la DMT" dans la structure de la VMT)

La DMT se présente ainsi :

  • Pointeur sur la DMT précédente (longint)
  • index (longint)
  • offset (longint)
  • Nombre de méthodes dans la DMT (word)
  • 1. Index méthode (word)
  • n. Index méthode (word)
  • 1. Pointeur méhode (longint)
  • n. Pointeur méthode (longint)

Pour le stockage d'une méthode on utilise en gros la procédure suivante :
Chaque méthode reçoit un numéro. Dans la DMT apparaît d'abord le nombre de méthodes stockées, puis leurs index et enfin leurs pointeurs.

Ainsi, si l'on a besoin d'une méthode, on connait son numéro. Avec celui-ci on cherche l'index de la méthode dans la DMT et ensuite on trouve son pointeur.

Exemple : le numéro de la méthode a été trouvé à l'index 3 -> Son pointeur se trouve en "3. Pointeur méthode"

Mis à jour le 20 janvier 2014 Bestiol Laurent Dardenne

En Delphi, il n'existe pas de moyen natif pour dupliquer un objet. Pour remédier à ce problème, il existe une classe, TPersistent, dont descendent toutes les classes susceptibles de devoir être dupliquées.

TPersistent est une classe abstraite enfant de TObject et parente de TComponent, TStrings et autres classes bien connues de la VCL.
Cette classe déclare une méthode Assign virtuelle ( virtual) publique et une méthode AssignTo protégée ( protected). L'implémentation de Assign dans TPersistent appelle la méthode AssignTo de l'objet en paramètre avec Self en paramètre. La méthode AssignTo déclenche une exception EConvertError avec comme message "Impossible d'assigner %s à %s" (avec les %s les noms des classes de source et de destination).

À partir de là, il est possible, lorsqu'on crée une classe descendante de TPersistent, de sucharger (override) ces méthodes afin d'assigner correctement un objet à un autre.

Par exemple, si vous voulez créer une classe TVoiture dont les objets puissent être dupliqués, il faut la faire hériter de TPersistent, et surcharger la méthode Assign afin de faire l'assignation :

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
procedure TVoiture.Assign(Source : TPersistent); 
begin 
  if Source is TVoiture then with TVoiture(Source) do 
  begin 
    Self.FMarque := FMarque; 
    Self.FCouleur := FCouleur; 
  end else inherited; 
end;
Après, créons une classe descendante de TVoiture, par exemple TAutreVoiture avec une cylindrée et un type de carburant, il suffit de re-surcharger la méthode Assign :
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
procedure TAutreVoiture.Assign(Source : TPersistent); 
begin 
  inherited; 
  if Source is TAutreVoiture then with TAutreVoiture(Source) do 
  begin 
    Self.FCylindree := FCylindree; 
    Self.FCarburant := FCarburant; 
  end; 
end;
Sachez à ce propos que tous les composants de la VCL surchagent correctement Assign et/ou AssignTo afin de pouvoir se copier.

Mis à jour le 20 janvier 2014 sjrd

Les procédures n'étant pas des méthodes d'objet il n'est pas possible d'utiliser RTTI pour en trouver les adresses. Cependant il existe une ruse pour forcer le compilateur à garder une trace des noms des procédures et fonctions voulues afin que l'on puisse les appeler par leur nom.

Cette méthode consiste à exporter les noms de procédure comme on le ferait dans une dll. Une fois les fonctions exportées on utilise la même méthode pour les appeler que la méthode utilisée pour l'appel d'une fonction de dll.

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Function Additionner(x, y: Integer): Integer; 
Begin 
  Result:=x+y; 
End; 
  
Function Soustraire(x, y: Integer): Integer; 
Begin 
  Result:=x-y; 
End; 
  
Function Multiplier(x, y: Integer): Integer; 
Begin 
  Result:=x*y; 
End; 
  
Exports Additionner,SousTraire,Multiplier; 
  
procedure TForm1.Button1Click(Sender: TObject); 
var H: HModule; 
    F: Function(X,Y:Integer):Integer; 
begin 
  H := GetModuleHandle(nil); 
  if H <> 0 then 
  begin 
    F := GetProcAddress(H, PChar(Edit1.Text)); 
    if Assigned(F) then 
      ShowMessage(IntToStr(F(SpinEdit1.Value,SpinEdit2.Value))) 
    Else 
      ShowMessage('Fonction non trouvée !'); 
  End; 
  
//  SetWindowLong(Memo1.Handle,GWL_STYLE,GetWindowLong(Memo1.Handle,GWL_STYLE)Or ES_UPPERCASE); 
end;
Notez l'ajout de la clause Exports pour déclarer les fonctions comme on le ferait dans une dll.

Mis à jour le 20 janvier 2014 Delphiprog Nono40

Lorsque le code source est compilé, chaque méthode créée occupe un emplacement bien précis en mémoire. Pour appeler une méthode donnée, il faut donc pouvoir récupérer l'adresse de cette dernière en mémoire : ceci se fait à l'aide de MethodAddress.
Cependant, la signature de la fonction est requise pour pouvoir l'appeler (dans le cas des surcharges, il ne sera pas possible par exemple de définir quelle est la fonction à appeler).

Le code suivant nous permet d'appeler une méthode (NouvelleMethode) qui reçoit deux entiers en paramètre et retourne un entier par son nom :

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Var  
  Meth : Function(x,y:Integer):Integer Of Object; 
 //on définit le prototype de la fonction à appeler 
Begin 
  // La méthode est cherchée par son nom 
  @Meth :=MethodAddress('NouvelleMethode'); 
  If @Meth <> Nil Then  
  Begin 
    // Si l'adresse est trouvée elle est appelée normalement 
    Resultat.Caption := (IntToStr(Meth(A.Value,B.Value))); 
  End Else 
  Begin 
    // Sinon erreur 
    ShowMessage('Nom de méthode introuvable !'); 
  End; 
End;
Vous pouvez trouver un exemple pratique dans le lien ci-dessous :

Mis à jour le 20 janvier 2014 Mac LAK Nono40

Afin d'affecter la même valeur à plusieurs variables, nous allons utiliser la notion de tableau ouverts.
Un tableau ouvert nous permet de construire un tableau d'élément sans spécifier ses dimensions. Nous utilisons les primitives Low et High pour connaître ses dimensions.

Nous utiliserons une procédure d'affectation par type de variable; c'est à dire une procédure qui prendra en paramètre la valeur à affecter ainsi qu'un tableau de variables pouvant accepter cette valeur.

Pour les entiers, ce sera par exemple :

Code delphi : Sélectionner tout
1
2
3
4
5
6
procedure SetMultiValueInteger(AValue:integer;T:Array of Integer);  
var i:Integer;  
begin  
  for i:=Low(T) to High(T) do  
  T[i]:=AValue;  
end;
Pour les chaînes de caractères :
Code delphi : Sélectionner tout
1
2
3
4
5
6
procedure SetMultiValueString(AValue:string;T:Array of string);  
var i:Integer;  
begin  
  for i:=Low(T) to High(T) do  
  T[i]:=AValue;  
end;
Pour les booléens :
Code delphi : Sélectionner tout
1
2
3
4
5
6
procedure SetMultiValueBoolean(AValue:boolean;T:Array of string);  
var i:Integer;  
begin  
  for i:=Low(T) to High(T) do  
  T[i]:=AValue;  
end;
etc.

Pour tester notre code, il nous suffira alors d'écrire quelque chose comme :
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
var  i1,i2,i3:Integer;  
     s1,s2,s3,s4,s5:string;  
     b1,b2:boolean;  
begin  
  SetMultiValueInteger(5,[i1,i2,i3]);  
  SetMultiValueString('Toto',[s1,s2,s3,s4,s5]);  
  SetMultiValueBoolean(True,[b1,b2]);  
end;

Mis à jour le 20 janvier 2014 LadyWasky

Il est possible de retrouver une méthode ou une procédure en fonction de son nom, mais parfois on aimerait retrouver l'ensemble des méthodes d'une fiche. À l'aide des RTTI il est possible de récupérer des informations d'une classe.
Voici comment procéder, le résultat est mis dans une TStringGrid.

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
procedure TForm1.GetObjectInfo(Objet: TObject); 
var 
 PData   : PTypeData; 
 PListe  : PPropList; 
 NbProps, 
 I       : Integer; 
 Method  : TMethod; 
 iPosGrid : integer; 
begin 
  PData := GetTypeData(PTypeInfo(Objet.ClassInfo)); 
  NbProps := PData^.PropCount; 
  
  New(PListe); 
  GetPropInfos(PTypeInfo(Objet.ClassInfo), PListe); 
  SortPropList(PListe,NbProps); 
  
  with StringGrid1 do 
  begin 
    ColCount := 3; 
    RowCount := NbProps + 1; 
    for i := 0 to RowCount -1 do 
      Cells[1,i] := ''; 
    iPosGrid := 1; 
    for I := 0 to NbProps -1 do 
    begin 
      Cells[0,iPosGrid] := PListe^[I]^.Name; 
      Cells[2,IposGrid] := PListe^[I]^.PropType^.Name; 
  
       case PListe^[I]^.PropType^.Kind of 
            tkInteger: begin 
              if UpperCase(PListe^[I]^.PropType^.Name) = 'TCOLOR' then 
                Cells[1,iPosGrid] := IntToHex(GetOrdProp(Objet, PListe^[I]),6) 
              else 
                Cells[1,iPosGrid] := IntToStr(GetOrdProp(Objet, PListe^[I])); 
            end; 
  
            tkString,tkWString,tkLString : 
              Cells[1,iPosGrid] := GetStrProp(Objet, PListe^[I]); 
  
            tkFloat : 
              Cells[1,iPosGrid] := FormatFloat('0.0000000',GetFloatProp(Objet, PListe^[I])); 
            tkEnumeration : begin 
              if UpperCase(PListe^[I]^.PropType^.Name) = 'BOOLEAN' then 
                Case GetOrdProp(Objet, PListe^[I]) of 
                  0: Cells[1,iPosGrid] := 'False'; 
                  1: Cells[1,iPosGrid] := 'True'; 
                  else 
                     Cells[1,iPosGrid] := 'Inconnue'; 
                end; 
            end; 
            tkMethod : 
            begin 
              Method := GetMethodProp(Self, PListe^[I]); 
              if Method.Code <> NIL then 
                Cells[1,iPosGrid] := ' (' + 
                  TObject(Method.Data).MethodName(Method.Code) + ')'; 
            end; 
            tkUnknown: 
              Cells[1,iPosGrid] := 'Inconnue'; 
       end; // case 
       inc(iPosGrid); 
    end; 
  end; 
  
  Dispose(PListe); 
end;
La partie qui nous intéresse le plus est la suivante :
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
tkMethod : begin 
             Method := GetMethodProp(Self, PListe^[i]); 
             With Method 
              begin 
               if Code <> NIL then 
               Cells[1,iPosGrid] := ' (' +TObject(Data).MethodName(Code) + ')'; 
              end; 
            end;
Il reste un problème, comment exécuter la méthode récupérée ?
Dans le cas d'un gestionnaire d'événement on doit transtyper le résultat obtenu avec le prototype de la méthode à appeler :
Code delphi : Sélectionner tout
1
2
type 
 TTraitement= procedure (S:String) of object;
Par exemple :
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
procedure AfficheDetails(Informations : TPropInfo); 
var 
 TypePropriete : String; 
 DonneePropriete: PTypeData; 
 Method : TMethod; 
 Resultat : String; 
... 
                   //Exécute le code associé à la propriété 
                  Method := GetMethodProp(UnObjet, Informations.Name); 
                  if Method.Code <> NIL then //UnObjet.OnTraitement:=Nil 
                   begin 
                    Resultat:=''; 
                    TTraitement(Method)(Resultat); 
                    Writeln(Resultat); 
                   end;
Notes :
Les RTTI ne fonctionnent complètement que sur les classes dérivées de TPersistent.

Mis à jour le 20 janvier 2014 Laurent Dardenne Rayek

Introduction aux RTTI sous Delphi, par Laurent Dardenne

Voici la situation : vous avez implémenté une routine ou méthode avec un paramètre (appelé Param) déclaré const, et vous remarquez en pas-à-pas la chose suivante. Un appel à une autre routine/méthode, sans même passer Param en paramètre, modifie Param !

L'explication rationnelle du problème (si si, il y en a une) : voir lien ci-dessous.

Mis à jour le 20 janvier 2014 sjrd

Pour savoir si une chaîne de caractères fait partie d'un tableau, on utilise la fonction MatchStr ou MatchText fournies par l'unité System.StrUtils.
Voici une fonction très courte pour faire l'équivalent sur un tableau d'entiers :

Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
  
uses System.Generics.Collections; 
  
function MatchInt(Valeur: NativeInt; Tableau: array of NativeInt; out Idx: Integer): Boolean; 
begin 
  TArray.Sort<NativeInt>(Tableau); 
  Result := TArray.BinarySearch<NativeInt>(Tableau, Valeur, Idx); 
end;

Exemple :
Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
  
var 
  Idx: Integer; 
  I: array of NativeInt; 
begin 
  SetLength(I, 8); 
  I := [25, 14, 1, 2, 3,  23, 45, 78]; 
  if MatchInt(78, I, Idx) then 
    ShowMessage(Idx.ToString);

Mis à jour le 1er juin 2024 Papy214

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.