Accueil
Rechercher:
sur developpez.com sur les forums
Forums | Tutoriels | F.A.Q's | Participez | Hébergement | Contacts
Club Emploi Blogs   TV   Dév. Web PHP XML Python Autres 2D-3D-Jeux Sécurité Windows Linux PC Mac
Accueil Conception Java DotNET Visual Basic  C  C++ Delphi Eclipse MS-Office SQL & SGBD Oracle  4D  Business Intelligence
FORUMS DELPHI F.A.Q DELPHI TUTORIELS DELPHI LIVRES COMPOSANTS SOURCES DEFI TELECHARGEZ DELPHI TV

Conversion du langage C# vers Delphi 2005 pour .NET

Date de publication : 08/02/2004 , Date de mise a jour : 23/07/2005

Par Laurent Dardenne (Contributions)
 

Vous trouverez dans cet article des indications de conversion du langage C# vers Delphi 2005 pour .NET.


1. Public concerné
2. Introduction
3. Modificateur de types et de membres de types
3-1. Modificateurs d'accès
3-2. Autres modificateurs
3-2-1. Exemple de procédure external
3-2-2. Exemple d'initialisation de champ statique
4. Opérateurs
5. Types
6. Tests
6-1. ?:
6-2. switch
6-3. Test de validité sur des pointeurs (null)
7. Structures itératives
7-1. While
7-2. Do/While
7-3. For
7-4. Foreach
7-5. Rupture de séquence
7-5-1. Break
7-5-2. Continue
7-5-3. Exit
8. Exception
8-1. Déclencher une exception
8-2. Gestion d'une exception
8-3. Redéclencher une exception
8-4. Bloc finally
9. Classe
9-1. Héritage
9-2. Constructeur
9-3. Destructeur
9-4. Type de membres
9-5. Méthode
9-5-1. Procédure
9-5-2. Fonction
9-5-2-1. Fonction delegate
9-5-2-2. Gestionnaire d'événement
9-6. Passage de paramètres
9-7. Paramètres en nombre variable
10. Propriétés
10-1. Comparaison entre les propriétés et les indexeurs
11. Structure de données
11-1. Struct
11-2. Tableau
11-2-1. Tableau de tableaux (jagged array)
12. Déclaration de variables
13. Instructions diverses
13-1. Utilisation de mot-clé réservé
14. Attributs
15. C# 2.0 et les génériques, ...


1. Public concerné


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.

 The C# Design Process : A Conversation with Anders Hejlsberg.

 Pages Microsoft dédiées au langage C# notamment les spécifications 2.0.

Un cours complet sur le C# par RM di Scala.

Un second cours complet sur le C# (lien direct sur un fichier au format Pdf).

 Conversion C# vers Delphi : un outil Borland en version BETA, sa version en  add-in pour l'IDE Delphi 2005.

Conversion C++ vers C#


3. Modificateur de types et de membres de types

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.

Delphi .Net : Variable de thread ?

3-2-1. Exemple de procédure external

[DllImport("kernel32", SetLastError=true)] static extern bool CreateDirectory(string name, SecurityAttribute sa);
[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 { static void Main() { Console.WriteLine("{0} {1}", B.Y, A.X); } public static int F(string s) { Console.WriteLine(s); return 1; } } class A { public static int X = Test.F("Init A"); }
Dans ce cas sous Delphi on utilisera une variable de classe :

A=Class Public // champs de classe, static Class var X : Integer; end;
Le code suivant qui contient du code dans la déclaration du type

public static readonly DBBool dbNull = new DBBool(0);
est convertie en utilisant un constructeur de classe.

TDBBool = record Strict private // Champ privé pour stocker la valeur du type FValeur : integer; // champs de classe, static Class var FdbNull : TDBBool; Class Constructor CCreate; Private // Le constructeur ne doit pas être accessible // Private pour TDBBool.dbTrue:=TDBBool.Create(0); Constructor Create(AValeur: DBType); ... end; implementation Constructor TDBBool.Create(AValeur: DBType); Begin FValeur:=AValeur; end; Class Constructor 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.
La surcharge d'opérateurs en C# :

public static implicit operator DBBool(bool x)
La surcharge d'opérateurs en Delphi .Net :

Class operator TDBBool.Explicit(x: TDBBool): Boolean;
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 else if 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.

public override string 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: throw new InvalidOperationException(); } }
Function TDBBool.ToString: String; begin Case 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; else Raise 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

public static void 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

public static void 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; Begin for i := 1 to 10 do begin Console.WriteLine(i); end;

7-4. Foreach

// Utilisation avec les tableaux using System; class MainClass { public static void Main() { int odd = 0, even = 0; int[] arr = new int [] {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 : Array of integer; Begin odd:= 0; even:=0; arr:= New(array[] of integer,(0,1,2,5,7,8,11)); For i in arr Do if (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.


8. Exception


8-1. Déclencher une exception

public static explicit operator bool(DBBool x) { if (x.value == 0) throw new InvalidOperationException(); return x.value > 0; }
Class operator TDBBool.Explicit(x: TDBBool): Boolean; const cdbNull=0; cdbTrue=1; begin If x.FValeur=cdbNull then raise InvalidOperationException.Create else Result:=x.FValeur=cdbTrue; end;

8-2. Gestion d'une exception

public override bool Equals(object o) { try { return (bool) (this == (DBBool) o); } catch { return false; } }
Function TDBBool.Equals(x: TObject):Boolean; begin try 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 ... except On E:InvalidOperationException do begin Console.WriteLine('b est NULL') Raise; // L'exception concernée, ici E, est implicite end; 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

public static void 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); begin inherited Create; // En Delphi .NET l'appel de l'ancêtre est obligatoire. Self.n = n; end; ...

9-3. Destructeur

La syntaxe suivante déclare un destructeur :

public class test{ ... ~Test(){ // Cleanup statements. CloseHandle(Handle); } ... }
Identique au code :

public class test{ ... protected override void Finalize() { try { // Cleanup statements. CloseHandle(Handle); } finally { base.Finalize(); } }
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; begin try CloseHandle(handle.ToInt32); finally inherited; 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.

static double CalculateArea(int r) { double area; area = r*r*Math.PI; return area; }
function CalculateArea(r: integer):double; var area : double; begin area:= r*r*Math.PI; Result:=area; Exit; end;

9-5-2-1. Fonction delegate

En C#
delegate void MethodeDelegate(int i);
En Delphi .NET
MethodeDelegate = function(x: Integer): string of object;

9-5-2-2. Gestionnaire d'événement

En C#
public delegate void EventHandler(Object sender, EventArgs e);
En Delphi .NET
TEventHandler = Procedure (Sender:TObject ; e : EventArgs) Of Object;
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 classe Property 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.

Delphi .Net :
Valeur par défaut
identifiant=valeur C# : TODO

Delphi .Net : TODO


9-7. Paramètres en nombre variable

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.

public class Console { public static void Write(string fmt, params object[] args) {...} public static void WriteLine(string fmt, params object[] args) {...} ... }
Sous Delphi .Net ce type ne nécessite pas l'utilisation d'un mot-clé, on le déclare par un paramètre tableau ouvert contenant des TObjet.

Procedure(fmt: string; Args : array of TObject);


10. Propriétés

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 { private int myAge = 0; // Déclare une propriété Age de type integer: public int 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. public abstract double Area { get; }
Surcharge de propriété :

// Redéclaration de la propriété Area dans une classe dérivée public override double 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

public struct Point { public int 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 = new int[5]; arr[0] = 2;
var arr : array[0..4] of integer; // tableau statique begin arr[0]:= 2;
Utilisation d'un initialiseur de tableau

int[] arr = new int[3] {0, 1, 2};
arr:= New(array[] of integer,(0,1,2)); ...

11-2-1. Tableau de tableaux (jagged array)

// tableau de tableaux (jagged array) byte[][] scores = new byte[5][]; // Création du "jagged array" for (int i = 0; i < scores.Length; i++) { scores[i] = new byte[i+3]; }
type TScores = Array of Array of byte; // Tableaux dynamiques multi-dimensionnels var 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=Class public 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 !
lock() Monitor
C# : lock(directory) {...}

Delphi .Net :

Monitor.Enter(directory);
try
...
finally
Monitor.Exit(directory);
// // La déclaration des commentaires est identique pour // et /* */.
P.x = P.y= 10; P.x:=10;
P.y:=10;
Assignation multiple.
123.ToString Integer(123).ToString Delphi .Net : L'utilisation de méthode sur des types primitif nécessite un transtypage.
Notez la seconde possibilité d'utilisation du mot-clé using en C#:
L'instruction using définit une portée au bout de laquelle un objet est supprimé.

using (Object MonObjet= new Object) { MonObjet.FaitqqChose; }
En Delphi .Net ce mot-clé peut être remplacé par la construction With do suivante :

with MonObjet.Create do try MonObjet.FaitqqChose; finally if Assigned(MonObjet) then (MonObjet as IDisposable).Dispose; end;
L'objet que vous instanciez doit implémenter l'interface System.IDisposable.


13-1. Utilisation de mot-clé réservé

public FileInfo lockFileInfo; public override bool Obtain() { try { FileStream fs = lockFileInfo.Create(); fs.Close(); } catch { return false; } return true; }
var fs: FileStream; begin try fs := lockFileInfo.Create('');
Provoque l'erreur :

[Erreur] Project1.dpr(18): E2382 Impossible d'appeler des constructeurs utilisant des variables d'instance
Le mot Create étant un mot-clé réservé sous Delphi pour créer une nouvelle instance. Dans ce cas il faut utiliser le caractère éperluet &.

var fs: FileStream; lockFileInfo: FileInfo; Begin try lockFileInfo := FileInfo.Create('MyFile.txt'); fs := lockFileInfo.&Create; except fs.Close(); end;

14. Attributs

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.


15. C# 2.0 et les génériques, ...

C#, les possibles évolutions

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.

C# 3.0 (Comega) la fusion de la POO du SQL et d'XML ?

Exemple :

{ 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); }


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 oeuvre intellectuelle protégée par les droits d'auteurs. Copyright © 2005 Laurent Dardenne. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.

Responsables bénévoles de la rubrique Delphi : Bruno Guérangé et Pierre Rodriguez - Contacter par EMail :
Vos questions techniques : forum d'entraide Delphi - Publiez vos articles, tutoriels et cours
et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones
Nous contacter - Copyright © 2000-2008 www.developpez.com - Legal informations.