Testé sous Dot Net 1.1 avec les spécifications du C# v1.2 et Delphi 2005. Version 1.0
Je tiens a remercier Nono40, Pascal Jankowski et Sébastien Doeraene (sjrd) pour leurs relectures et suggestions pertinentes ainsi que pour leurs corrections orthographiques.
Cet article utilise quelques URL locales vers la documentation de .NET de Microsoft et de Delphi 2005.
2. Introduction
Étant en phase d'apprentissage sur le langage Delphi 2005 pour .NET, j'ai très vite compris que la conversion des exemples issus du SDK allait poser quelques problèmes aux nombreux débutants.
Cette approche peut paraître paradoxale mais la compréhension du langage C# m'a, tout compte fait, rendu service même si cela a été un peu délicat dans les premiers temps. Il ne s'agit pas ici d'un cours complet sur le C# ni sur Delphi pour .NET mais d'une suite d'indications. Le contexte pouvant influencer la conversion d'un code C# vers Delphi pour .NET.
Il va sans dire que cet article n'est pas exhaustif sur le sujet et sera mis à jour régulièrement, vos remarques et propositions y contribueront.
Concernant le C#, j'ai le plus souvent utilisé la terminologie propre au SDK.
Le symbole NI signifie fonctionnalité non implémenté en Delphi pour .Net.
Attention, certaines possibilités du langage C# ne sont pas compatible avec la CLS.
Extrait du SDK :
Pour interagir entièrement avec d'autres objets quel que soit le langage dans lequel ils ont été implémentés,
les objets ne doivent exposer aux appelants que les fonctionnalités qui sont communes à tous les langages avec
lesquels ils doivent fonctionner. Pour cette raison, un ensemble de fonctionnalités de langage appelé
spécification CLS (Common Language Specification), qui comprend les fonctionnalités de langage de base
nécessaires à de nombreuses applications, a été défini.
Il est donc conseillé de n'utiliser que le C# CLS Compliant. L'ajout de l'attribut personnalisé CLSCompliant indique au compilateur de vérifier si le code généré respecte bien les spécifications de la CLS.
Extrait du SDK :
Afin qu'un module soit conforme CLS, via [module:System.CLCSompliant(true)], il doit être généré avec l'option
/target:module du compilateur.
Pour ceux qui souhaiteraient aborder plus en détails la comparaison entre le langage C# et le langage Delphi pour .NET, consultez le cours complet sur le C# de RM di Scala .
Vous trouverez ici quelques liens utiles glanés au cours de ma rédaction qui vous permettront d'aborder plus précisément certains points :
Anders Hejlsberg : Une courte biographie d'un des concepteurs du C# et de Delphi.
Ils permettent de modifier les déclarations des types et membres de types.
3-1. Modificateurs d'accès
Le compilateur Delphi pour .NET prend en charge des paramètres de visibilité supplémentaires conformes à la spécification CLS (Common Language Specification) .NET.
C#
Delphi .NET
Commentaire
public
public
C# : L'accès n'est pas limité.
Delphi .Net : Un membre public est visible partout où la classe peut être référencée.
protected
protected
C# : L'accès est restreint à la classe conteneur ou aux types dérivés de la classe conteneur.
Delphi .Net : Un membre protégé est visible partout dans le module où la classe est déclarée et dans toute classe descendante, indépendemment du module où la classe descendante est définie.
Le spécificateur de visibilité protégée de Delphi correspond à la visibilité assemblage ou famille du CLR.
protected internal
strict protected
C# : L'accès est restreint à l'assembly en cours ou aux types dérivés de la classe conteneur.
Delphi .Net : Les membres de classes dont la visibilité est privée stricte (strict protected) ne sont accessibles que dans la classe dans laquelle ils sont déclarés. Ils ne sont pas visibles pour les procédures ou fonctions déclarées dans la même unité.
private
private
C# : L'accès est restreint au type conteneur.
Les membres privés sont accessibles uniquement dans le corps de la classe ou du struct où ils sont déclarés. Les types imbriqués dans le même corps peuvent également accéder à ces membres privés.
Delphi .Net : Un membre privé est invisible hors de l'unité ou du programme dans lequel la classe est déclarée.
Le spécificateur de visibilité privée traditionnelle de Delphi correspond à la visibilité assemblage du CLR.
internal
strict private
C# : L'accès est restreint à l'assembly en cours. Les membres internes sont accessibles seulement dans les fichiers du même assembly.
Delphi .Net : Les membres de classes dont la visibilité est privée stricte (strict private) ne sont accessibles que dans la classe dans laquelle ils sont déclarés. Ils ne sont pas visibles pour les procédures ou fonctions déclarées dans la même unité.
Par défaut dans une classe en C# tous les membres sans qualificateur d'accés sont considérés comme privés (private).
Les types imbriqués, qui sont membres d'autres types, peuvent disposer d'accessibilités déclarées, voir "Guide de référence du programmeur C#" proposé dans l'aide de Delphi 2005.
A noter sous Delphi .Net :
Published : Accessible à tout le code et depuis l'inspecteur d'objets.
Automated n'est plus supporté en .NET.
3-2. Autres modificateurs
C#
Delphi .NET
Commentaire
static
class
C# : Utilisez le modificateur static pour déclarer un membre statique, qui appartient au type lui-même plutôt qu'à un objet spécifique.
Delphi .Net : Référence de classe ou méthode de classe. Les contructeurs de classe sont également possible.
static extern
external
C# : Les méthodes externes sont implémentées en externe, en utilisant généralement un langage autre que C#.
virtual
virtual
C# : Lorsqu'une déclaration de méthode d'instance comprend un modificateur virtual, cette méthode est une méthode virtuelle.
Dans un appel de méthode virtuelle, le type au moment de l'exécution de l'instance pour lequel l'appel intervient détermine l'implémentation de la méthode réelle à appeler.
Déclarer une méthode ou un accesseur dont l'implémentation peut être modifiée par un membre de redéfinition dans une classe dérivée.
abstract
abstract
C# : Le modificateur abstract est utilisé pour une méthode ou une propriété d'une classe qui n'a pas d'implémentation ou pour une classe qui comprend des méthodes de ce type.
Delphi .Net : Lorsqu'une méthode est déclarée abstract dans une classe ancêtre, vous devez la redéclarer et l'implémenter dans tout composant/classe descendante avant d'utiliser le nouveau composant/nouvelle classe.
overload
C# : La surcharge existe mais il n'existe pas de mot clés associé. La liste d'arguments différents pour des méthodes de même nom détermine la surcharge.
Delphi .Net : Les membres de classes dont la visibilité est protégée stricte (strict private) sont visibles dans la classe dans laquelle ils sont déclarés et dans toutes les classes dérivées, quel que soit l'endroit où elles sont déclarées.
La redéfinition (ou surcharge)
Les routines redéfinies doivent être redéclarées avec la directive overload et doivent utiliser une liste d'arguments différents.
override
C# : Fournit une nouvelle implémentation d'un membre virtuel hérité d'une classe de base. Il n'existe pas de mot clé pour préciser la surcharge.
Delphi .Net : Surcharger une méthode signifie l'étendre ou la redéfinir plutôt que la remplacer. Une classe descendante peut surcharger toutes ses méthodes virtuelles héritées.
const
const
C# : Spécifier que la valeur du champ ou la variable locale ne peut pas être modifiée.
Delphi .Net : Les possibilités d'initialisation ne sont pas identiques.
readonly
NI
C# : Déclarer un champ auquel seules peuvent être attribuées des valeurs au sein de la déclaration ou dans un constructeur de la même classe.
Delphi .Net : Utiliser une propriété pour interdire l'accés. Si vous ne déclarez aucune méthode read, la propriété fonctionne uniquement en écriture.
sealed
sealed
C# : Spécifier qu'une classe ne peut pas être héritée.
unsafe
NI
C# : Déclarer un contexte non sécurisé.
Delphi .Net : Voir la directive de compilation {UNSAFECODE ON}.
volatile
NI
C# : Indiquer qu'un champ peut être modifié dans le programme par quelque chose tel que le système d'exploitation, le matériel ou un thread s'exécutant simultanément.
[DllImport('user32.dll', SetLastError=true)]
function CreateDirectory(name: string ; sa : SecurityAttribute):Boolean; external;
3-2-2. Exemple d'initialisation de champ statique
using System;
class Test
{
staticvoid Main() {
Console.WriteLine("{0} {1}", B.Y, A.X);
}
publicstaticint F(string s) {
Console.WriteLine(s);
return 1;
}
}
class A
{
publicstaticint X = Test.F("Init A");
}
Dans ce cas sous Delphi on utilisera une variable de classe :
A=ClassPublic // champs de classe, staticClassvar X : Integer;
end;
Le code suivant qui contient du code dans la déclaration du type
publicstaticreadonly DBBool dbNull = new DBBool(0);
est convertie en utilisant un constructeur de classe.
TDBBool = recordStrictprivate // Champ privé pour stocker la valeur du type
FValeur : integer;
// champs de classe, staticClassvar FdbNull : TDBBool;
ClassConstructor CCreate;
Private // Le constructeur ne doit pas être accessible // Private pour TDBBool.dbTrue:=TDBBool.Create(0);Constructor Create(AValeur: DBType);
...
end;
implementationConstructor TDBBool.Create(AValeur: DBType);
Begin
FValeur:=AValeur;
end;
ClassConstructor TDBBool.CCreate;
Begin // Initialise les valeurs possibles du type
TDBBool.FdbNull.FValeur:=cdbNull;
end;
Vous trouverez ici la conversion du code complet de cette exemple de classe en C#.
4. Opérateurs
Catégorie d'opérateurs
C#
Delphi .NET
Commentaire
Arithmétique
+ , - , * , / , % (modulo)
+ , - , * , / et div , mod
C# :
Delphi .Net : / pour une division réelle, et div pour une divisons entière
Logique binaire
&, |, ^, !, ~
AND, OR, XOR, NOT, NOT
C# : L'opérateur ~ effectue une opération de complément de bits sur son opérande. Les opérateurs de complément de bits sont prédéfinis pour int, uint, long et ulong.
! est l'opérateur de négation logique
Logique booléen
&&, ||, true, false
AND, OR, TRUE, FALSE
Concaténation de chaînes
+
+
Incrément, décrément
++, --
Inc(), Dec()
Déplacement
<<, >>
Shl, Shr
L'opérateur de déplacement vers la gauche (<<) ou la droite (>>) déplace le premier opérande vers la gauche ou la droite du nombre de bits spécifié par le second opérande.
Relationnel
==, !=, <, >, <=, >=
=, <>, <, >, <=, >=
C# :
Delphi .Net : Les opérateurs relationnels =, <>, <, >, <= et >= acceptent tous des opérandes chaîne.
Les opérateurs relationnels = et <> opèrent également sur des classes.
Assignation
=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
:=, Inc(), Dec(), NI, idem,...
C# : Une expression de la forme x ^= y
est évaluée comme x = x ^ y
Delphi .Net : Les assignations non implémentés se font en deux passes ou dans la même instruction d'assignation.
Accès au membre
. , this
. , Self
L'opérateur point (.) est utilisé pour l'accès aux membres.
Indexation
[]
[]
Cast
datatype()
datatype()
Conditionnel
?:
If Then Else
L'opérateur conditionnel est associatif à droite.
Concaténation et suppression de délégué
+, -
Include, Exclude
Création d'objets
new
Create
voir aussi le chapitre : Structure de données-tableaux
Informations de type
as, is, sizeof, typeof
AS, IS, SIZEOF, NI
C# : L'opérateur typeof permet d'obtenir l'objet System.Type pour un type. Il peut être remplacé par l'appel de la méthode GetType.
Delphi .Net : Appliquer la fonction TypeOf standard à un type ne possédant pas de fonction virtuelle provoquera une erreur
Contrôle des exceptions de dépassement de capacité
checked, unchecked
Directives de compilation
C# : Dans un contexte non vérifié (unchecked), si une expression produit une valeur qui est hors de la plage du type de destination, le résultat est tronqué. Delphi .Net : Directive de compilation $Q: Contrôle la génération de code qui teste le dépassement de capacité. voir aussi $R
Adresse et adressage indirect
*, ->, [], &
Pointer, Pointer^.x, incrément d'adresse,@
Il s'agit d'instructions spécifiques à Win32, générant du code non sécurisé.
Sous Delphi .Net voir la directive UNSAFECODE
Ensemble
enum
Set of type
C# : Voir les méthodes de la classe enum
Delphi .Net : Ens1 = Set of 1..10; Ens1 := [1, 3, 5, 7, 9];
Les opérateurs suivants [+, -, *, <=, >=, =, <>, in] acceptent des ensembles comme opérandes.
Les opérateurs true et false du C# ne peuvent être surchargés sous Delphi .NET.
5. Types
Les types sont communs aux deux langages s'ils sont 'mappés' sur les types de System.xxx.
Sous Delphi 2005 pour .Net certains types sont des alias et d'autres des simulations.
Soyez attentif au fait que le comportement d'un code C#, particuliérement au niveaux des types, peut dépendre :
de directives de compilation, notamment /checked.
de convention de conversion, implicite ou explicite, différente.
6. Tests
6-1. ?:
L'expression évaluée doit avoir un résultat booléen en C#.
a ? b : c ? d : e
If a=true then b
elseif c=true then d
else e
6-2. switch
L'instruction de contrôle switch est convertie en case of. La partie default est convertie en else.
En C# l'instruction break indique la fin de la branche case, s'il n'y a pas de break l'exécution continue au cas suivant.
publicoverridestring ToString()
{
switch (value)
{
case -4
case -3
case -2:
Console.writeline("Exemple");
Break;
case -1:
return"DBBool.False";
case 0:
return"DBBool.Null";
case 1:
return"DBBool.True";
default:
thrownew InvalidOperationException();
}
}
Function TDBBool.ToString: String;
beginCase Fvaleur of
-4,
-3,
-2: begin
Console.writeline("Exemple");
end;
-1: begin
Result:='TDBBool.False';
Exit;
end;
0: begin
Result:='TDBBool.Null';
Exit;
end;
1: begin
Result:='TDBBool.True';
Exit;
end;
elseRaise InvalidOperationException.Create;
end;
end;
Dans ce dernier exemple Delphi, l'instruction Exit est nécessaire pour refléter exactement l'instruction return contenue dans le code C#.
6-3. Test de validité sur des pointeurs (null)
if (EventTest != null)
EventTest(this, new EventArgs());
Attention sous Delphi NULL est une fonction de Borland.Vcl.Variants permettant d'obtenir un variant Null.
Utilisez la constante prédéfinie nil.
Toute variable procédurale peut contenir la valeur nil, ce qui signifie qu'elle ne pointe sur rien. Pour tester si une variable procédurale est initialisée, utilisez la fonction standard Assigned
if Assigned(FEventTest) then
FEventTest(Self, EventArgs.Create);
7. Structures itératives
7-1. While
publicstaticvoid Main()
{
int n = 1;
while (n < 6) do
{
Console.WriteLine("la valeur courante de n est {0}", n);
n++;
}
}
procedure Main;
var n: integer;
begin
n:= 1;
while (n < 6)
begin
WriteLn('la valeur courante de n est ', n);
inc(n);
end;
end;
7-2. Do/While
publicstaticvoid Main ()
{
int x;
int y = 0;
do
{
x = y++; // post-incrémentation
Console.WriteLine(x);
}
while(y < 5);
}
procedure Main;
var x, y : integer;
begin
y:=0;
Repeat
x:=y;
inc(y);
Console.WriteLine(x);
Until (y >= 5);
end;
Ici prenez garde à l'inversion du test.
7-3. For
for (int i = 1; i <= 10; i++)
{
Console.WriteLine(i);
}
Var i: integer;
Beginfor i := 1 to 10 dobegin
Console.WriteLine(i);
end;
7-4. Foreach
// Utilisation avec les tableauxusing System;
class MainClass
{
publicstaticvoid Main()
{
int odd = 0, even = 0;
int[] arr = newint [] {0,1,2,5,7,8,11};
foreach (int i in arr)
{
if (i%2 == 0)
even++;
else
odd++;
}
Console.WriteLine("Trouvé {0} chiffre impair et {1} chiffre pair.",
odd, even) ;
}
}
Sous Delphi .NET on utilise un tableau multidimensionnel alloué dynamiquement.
var i, odd, even : integer;
arr : Arrayofinteger;
Begin
odd:= 0;
even:=0;
arr:= New(array[] ofinteger,(0,1,2,5,7,8,11));
For i in arr Doif (i mod 2 = 0)
then inc(even)
else inc(odd);
WriteLn('Trouvé '+ intToStr(odd)+' chiffre impair et '+intToStr(even)+' chiffre pair.') ;
Readln;
end;
Delphi pour .NET prend en charge l'itération du style for-element-in-collection sur les
conteneurs. Les modèles suivants d'itérations sur les conteneurs sont reconnus par le compilateur :
for Element in ArrayExpr do Instruction;
for Element in StringExpr do Instruction;
for Element in SetExpr do Instruction;
for Element in CollectionExpr do Instruction;
Pour utiliser la construction de boucle for-in sur une classe, cette dernière doit implémenter un modèle de collection prescrit. Consulter la documentation pour les détails de l'implémentation.
7-5. Rupture de séquence
7-5-1. Break
Comportement identique C# : L'instruction 'break' termine la boucle englobante la plus proche où l'instruction switch apparaît.
Delphi .Net : La procédure 'break' fait quitter le flux de contrôle d'une instruction for, while ou repeat et passe à la prochaine instruction qui suit l'instruction de boucle.
7-5-2. Continue
Comportement identique C# : L'instruction 'continue' transmet le contrôle à l'itération suivante de l'instruction d'itération englobante où elle apparaît.
Delphi .Net : La procédure 'continue' poursuit le flux de contrôle jusqu'à la prochaine itération d'une instruction for, while ou repeat.
7-5-3. Exit
Attention homonymie et comportement différent C# : Termine le processus et donne au système d'exploitation sous-jacent le code de sortie spécifié.
Delphi .Net : La procédure 'Exit' fait immédiatement passer le contrôle d'exécution en dehors de la procédure. Si la procédure en cours correspond au programme principal, Exit termine l'exécution du programme.
Function TDBBool.Equals(x: TObject):Boolean;
begintry
Result:= (Self = x as TDBBool);
except
Result:=False;
end;
end;
8-3. Redéclencher une exception
Une instruction throw peut être utilisée dans le bloc catch pour lever une nouvelle fois l'exception qui a été interceptée par l'instruction catch.
Par exemple :
try
...
catch (InvalidCastException e)
{
Console.WriteLine("b est NULL")
throw (e); // Redéclenche l'exception e avec ses paramètres
}
try
...
exceptOn E:InvalidOperationException dobegin
Console.WriteLine('b est NULL')
Raise; // L'exception concernée, ici E, est impliciteend;
end;
En C# on peut redéclencher une exception sans les paramètres : throw.
En Delphi .Net cette possibilité n'existe pas.
8-4. Bloc finally
publicstaticvoid Main()
{
int i = 123;
string s = "Une chaîne";
object o = s;
try
{
// conversion invalide ; o contient une string et pas un entier.
i = (int) o;
}
finally
{
Console.Write("i = {0}", i);
}
}
Procedure Main()
var
i: integer;
s: string;
o: TObject;
begin
i:= 123;
s:='Une chaîne';
o:=s;
try // conversion invalide ; o contient une string et pas un entier.
i = integer (o);
finally
Console.Write('i = {0}', i);
end;
end;
9. Classe
9-1. Héritage
C#
Delphi .NET
Commentaire
class TopEvent : BaseEvent {...
TForm1 = class(TForm) ...
9-2. Constructeur
Le constructeur porte le même nom que la classe et en respectant la casse.
L'utilisation du mot-clé this dans un constructeur indique l'appel du constructeur par défaut :
...
public Initialise(Int32 n): this(){
this.n = n;
}
...
...
constructor Initialise(n : integer);
begininherited Create; // En Delphi .NET l'appel de l'ancêtre est obligatoire.
Self.n = n;
end;
...
Le mot clé base est utilisé pour accéder aux membres de la classe de base à partir d'une classe dérivée et correspond au mot-clé inherited sous Delphi.
Le code C# précédent correspond au code Delphi .NET suivant :
procedure TTest.Finalize;
begintry
CloseHandle(handle.ToInt32);
finallyinherited;
end
end;
9-4. Type de membres
Les déclarations de classe peuvent contenir des déclarations pour des
constantes
champs
méthodes
propriétés
événements
indexeurs
opérateurs
constructeurs d'instance
constructeurs statiques
destructeurs
types imbriqués
L'initialisation de membres, dans la partie déclaration d'une classe, n'est pas possible sous Delphi .Net.
9-5. Méthode
9-5-1. Procédure
En C# le mot-clé void indique une fonction ne renvoyant aucun résultat ce qui est le cas d'une procédure sous Delphi .NET.
void UneMethode();
Procedure UneMethode;
9-5-2. Fonction
Le mot clé return est remplacé par la combinaison de Result et d'Exit.
TEventHandler = Procedure (Sender:TObject ; e : EventArgs) OfObject;
La composition de délégué en C# se fait avec les opérateurs suivants += et -=
La composition de délégué Delphi .NET se fait avec de la maniére suivante :
TCompte=Class
...
// Utilisation d'une propriété dans une classeProperty MonDelegue:TMonDelegue add FMonDelegue remove FMonDelegue;
...
end;
...
// L'ajout d'un délégué
Include(UnCompte.MonDelegue,@Traite);
...
// La suppression d'un délégué
Exclude(UnCompte.MonDelegue,@Traite);
...
9-6. Passage de paramètres
C#
Delphi .NET
Commentaire
int a
a:integer
Passage par valeur
C# : Si le paramètre est une référence, il est possible de le modifier. Toutefois, la tentative de réassignation du paramètre à un emplacement de mémoire différent s'effectue uniquement au sein de la méthode et n'affecte pas la variable d'origine.
Delphi .Net : idem
ref
Var
C# : Toute modification apportée au paramètre dans la méthode est reflétée dans cette variable lorsque la méthode appelante récupère le contrôle.
Delphi .Net :
const
Const
out
Out
C# : Toute modification apportée au paramètre dans la méthode est reflétée dans cette variable lorsque la méthode appelante récupère le contrôle.
Une variable passée en tant qu'argument out n'a pas besoin d'être initialisée. Toutefois, une valeur doit être attribuée au paramètre out avant le retour de la méthode.
Sous C# un tableau de paramètres est déclaré avec un modificateur params. Il ne peut exister qu'un tableau de paramètres pour une méthode donnée, et celui-ci doit être le dernier paramètre spécifié. Le type d'un tableau de paramètres est toujours un type tableau unidimensionnel.
Les modificateurs autorisés sont new, static, virtual, abstract, override et une combinaison valide des quatre modificateurs d'accès (public,...).
using System;
class Person
{
privateint myAge = 0;
// Déclare une propriété Age de type integer:publicint Age
{ // Déclare les méthodes accesseur.
get
{
return myAge;
}
set
{
myAge = value;
}
}
}
En C# la déclaration de méthodes accesseurs (Set et Get) est obligatoire. La variable value est ajoutée dans ce cas par le compilateur.
En Delphi .NET elles sont créées par le compilateur si on référence directement une variable.
Propriété en read-only :
// Area est une propriété en read-only.publicabstractdouble Area
{
get;
}
Surcharge de propriété :
// Redéclaration de la propriété Area dans une classe dérivéepublicoverridedouble Area
{
get
{
return mySide * mySide;
}
}
Sous Delphi pour .NET seules sont supportées les propriétés de type suivant :
Simple
Enuméré
Ensemble
Objet
Tableau
Déclarer une valeur par défaut pour une propriété n'a pas pour effet de définir cette propriété par cette valeur.
10-1. Comparaison entre les propriétés et les indexeurs
TODO : comparaison
Les indexeurs sont similaires aux propriétés. À l'exception des différences répertoriées dans le tableau ci-dessous, toutes les règles définies pour les accesseurs des propriétés s'appliquent aux accesseurs des indexeurs.
Propriété
Indexeur
Delphi .Net
Identifiée par son nom.
Identifié par sa signature.
Accès par le biais d'un nom simple ou de l'accès à un membre.
Accès par le biais de l'accès à un élément.
Peut être un membre statique ou un membre d'instance.
Doit être un membre d'instance.
Un accesseur get d'une propriété n'a aucun paramètre.
Un accesseur get d'un indexeur possède la même liste de paramètres formels que l'indexeur.
Un accesseur set d'une propriété contient le paramètre value implicite.
Un accesseur set d'un indexeur possède la même liste de paramètres formels que l'indexeur, outre le paramètre value.
11. Structure de données
11-1. Struct
publicstruct Point
{
publicint x, y;
public Point(int p1, int p2)
{
x = p1;
y = p2;
}
}
La construction d'une structure (struct en C#) se fait en 2 étapes sous Delphi .Net.
La première dans la partie Interface.
Type
Point = Record
x, y : integer;
constructor Point.Create(p1,p2 : integer) ;
end;
et la seconde dans la partie implementation.
constructor Point.Create(p1,p2 : integer) ;
begin
x:=p1;
y:=p2;
end;
end;
11-2. Tableau
Les tableaux sont des objets et peuvent être de type unidimensionnel, multidimensionnel et des tableaux de tableaux (jagged array).
int[] arr = newint[5];
arr[0] = 2;
var
arr : array[0..4] ofinteger; // tableau statiquebegin
arr[0]:= 2;
Utilisation d'un initialiseur de tableau
int[] arr = newint[3] {0, 1, 2};
arr:= New(array[] ofinteger,(0,1,2)); ...
11-2-1. Tableau de tableaux (jagged array)
// tableau de tableaux (jagged array)byte[][] scores = newbyte[5][];
// Création du "jagged array"for (int i = 0; i < scores.Length; i++)
{
scores[i] = newbyte[i+3];
}
type
TScores = ArrayofArrayof byte; // Tableaux dynamiques multi-dimensionnelsvar Scores :TScores;
i: integer;
begin
SetLength(Scores,10); // Allocation des lignes // Création du "jagged array"for i := Low(Scores) to High(Scores) do
SetLength(cores[i], i+3); // Allocation des colonnes
Le terme jagged peut être traduit par déchiquetée mais irrégulier semble plus approprié.
Jag voulant signifier déchiré (saoul) :*)
12. Déclaration de variables
Les variables en C# se déclarent tout de suite après la déclaration du nom de classe.
class ExempleVisible2 {
int a = 10; // Cette initialisation est déclarée dans le constructeur.int g (int x )
{ return 3*x-a;
}
ExempleVisible2=Classpublic
a : integer;
Function g(x : integer):Integer;
Constructor Create;
end;
// L'assignation de a = 10 du C# est à la charge du développeur en Delphi .NET.Constructor Create;
begin
a:=10;
end;
En C# on peut aussi déclarer des variables 'à la volée' directement le code mais cette possibilité n'est pas supportée sous Delphi pour .NET, ce langage restant déclaratif.
// Extrait de l'unité System.pas
...
var
LMainThread: System.Threading.Thread;
function MainThread: System.Threading.Thread;
begin
Result := LMainThread;
end;
var
LastRandSeed: Integer = -1;
RandomEngine: System.Random;
procedure InitRandom;
begin
...
13. Instructions diverses
C#
Delphi .NET
Commentaire
using
uses
Import de types définis dans d'autres espaces de noms, dans ce contexte le mot clé using est converti en uses .
Alias using
NI.
C# : Créer un alias pour un espace de noms (un alias using). using MyAlias = MyCompany.Proj.Nested;
Delphi .Net : Vous pouvez par contre utiliser l'alias de types (type et classe), vous n'aurez pas à qualifier complètement le nom.
Dans ce cas le mot clé using est converti en uses
fixed
GCHandle
C# : // must use fixed to get address of pt.x and pin pt in place while we use the pointer
fixed ( int* p = &pt.x ){
*p = 1;
}
Delphi .Net : cf. System.Runtime.InteropServices.GCHandle Attention pour développeurs confirmés !
Les attributs sont identiques aux 2 langages. Seul leur déclaration, cf. classe, diffère.
En C# la convention veux que l'on suffixe, lors de la déclaration, le nom de la classe avec Attribut mais pas dans l'utilisation (le compilateur C# se chargeant d'ajouter le suffixe).
Certains attributs, par exemple conditionnal, sont spécifiques au compilateur C# de Microsoft.
Extrait d'un interview de Danny Thorpe au sujet de Delphi 2005 :
Microsoft has .NET 2.0 announced for the next year. When can we expect Delphi 10 and what have you planned for it ? Probably the biggest item in terms of the compiler/language is implementing parameterized type syntax (generic types) in Delphi. We've had parameterized type syntax sketched out on the whiteboards here for ages but other stuff (platforms) kept taking priority. The general goal is to have a product release in 2005, shortly after .NET 2.0 is finalized and released.
{
Database db = new Database("db://amazon.com");
XML list = db.Search("Author like 'Hugh Darwen'");
foreach (XML book in list) {
wishlist.Add(book.Title + ", " + book.ISBN);
}