| Sviluppo Cross Language | ||
|
Differenze tra Value e Reference Type |
In questo esempio si vuole mettere in evidenza uno degli aspetti più interessanti della piattaforma .NET, ovvero l'estrema facilità di utilizzo di più linguaggi di programmazione nel contesto di un unico progetto. Saranno creati due assembly: il primo è una libreria di tipo DLL che definisce una semplice classe di base scritta con le estensioni gestite (managed extension) per C++; il secondo assembly è un eseguibile che definisce tre classi derivate scritte rispettivamente in C#, Visual Basic e in Intermediate Language. Questi tipi derivano l'uno dall'altro e infine dalla classe di base in managed C++. Per concludere l'eseguibile crea istanze di ognuno dei tipi derivati e chiama un metodo virtuale per uno. Questo esempio è puramente didattico e fortemente semplificato, ma fornisce un'idea di come .NET Framework sia un ambiente dove molti sviluppatori possono lavorare insieme indipendentemente dal linguaggio di programmazione scelto. VCBase.cpp #using mscorlib.dll
using namespace System;
__gc public class VCBase
{
protected:
VCBase(){
Console::WriteLine(" Executing the VCBase::VCBase() constructor");
}
public:
virtual void Method() = 0;
void MethodThatThrows(){
throw(new OutOfMemoryException("We are out of some resource!"));
}
};
Questo codice crea una semplice classe di base scritta in C++, gli altri moduli creeranno classi derivate da questa, ma saranno scritti in Visual Basic, C# e IL. Le considerazioni sull'assembly mscorlib.dll sono identiche a quelle viste nell'esempio precedente (hello world!). .NET Framework, offre una funzione di Garbage Collection (GC), che facilita lo sviluppo abilitando l'ambiente a tener traccia delle risorse, come gli oggetti, ed automaticamente rilasciarle quando non sono più necessarie. La keyword __gc nella dichiarazione della classe VCBase marca la classe come "gestita", permettendo questo meccanismo. Una scritta su console (" Executing the VCBase::VCBase() constructor") avvisa quando è creata una istanza della classe VCBase (constructor). Il metodo Method non fa nulla, ma non serve perchè verrà subito scavalcato da un Method da esso derivato nella classe in Visual Basic. Piuttosto che un throw esplicito, quello finale agisce in caso in cui il codice acceda a risorse non disponibili. VBDerived.vb Option Explicit On
Option Strict On
Imports System
Public Class VBDerived
Inherits VCBase
Public Sub New()
REM MyBase.New
Console.WriteLine(" Executing the VBDerived.New() constructor")
End Sub
Overrides Public Sub Method
Console.WriteLine(" Executing the VBDerived.Method() virtual method")
End Sub
Public Sub AnotherMethodThatThrows
Try
MyBase.MethodThatThrows()
Catch e As OutOfMemoryException
Throw(new ApplicationException("Some application function failed!", e))
End Try
End Sub
End Class
Questo codice dimostra un semplice tipo scritto
in Visual Basic e derivato da VCBase [Inherits
VCBase]... ILDerived.il .module extern VBDerived.netmodule
.class public auto ansi ILDerived
extends [.module VBDerived.netmodule]VBDerived
{
.method public specialname rtspecialname
instance void .ctor() il managed
{
.maxstack 1
.locals init (class System.Object[] V_0)
IL_0000: ldarg.0
IL_0001: call instance void [.module VBDerived.netmodule]VBDerived::.ctor()
IL_0006: ldstr " Executing the ILDerived::ctor() constructor"
IL_000b: call void [mscorlib]System.Console::WriteLine(class System.String)
IL_0010: ret
}
.method public virtual instance void Method() il managed
{
.maxstack 1
.locals init (class System.Object[] V_0)
IL_0000: ldstr " Executing the ILDerived::Method() virtual method"
IL_0005: call void [mscorlib]System.Console::WriteLine(class System.String)
IL_000a: ret
}
}
... la stessa cosa derivando in Intermediate Language la classe VBDerived definita qui sopra... CSDerived.cs using System;
public class CSDerived:ILDerived{
public CSDerived(){
Console.WriteLine(" Executing the CSDerived.CSDerived() constructor");
}
override public void Method(){
Console.WriteLine(" Executing the CSDerived.Method() virtual method");
}
}
... ed infine l'analogo in C#, derivato dalla classe ILDerived [class CSDerived:ILDerived]. CrossLang.cs using System;
using System.Security;
class App{
public static void Main(){
try{
CrossObj();
}catch(VerificationException){
Console.WriteLine("A VerificationException has been thrown "+
"(and caught). Run this\nsample from your local "+
"hard-drive to avoid this exception.");
}
}
static void CrossObj(){
// Crea un array di oggetti per immagazzinare quelli definiti
//negli altri linguaggi
VCBase[] objects = new VCBase[3];
// Carica nella posizione 0 dell'array l'oggetto
//creato usando IL
Console.WriteLine("\nCreating object: ILDerived");
objects[0] = new ILDerived();
// Carica nella posizione 1 dell'array l'oggetto
//creato usando C#
Console.WriteLine("\nCreating object: CSDerived");
objects[1] = new CSDerived();
// Carica nella posizione 2 dell'array l'oggetto
//creato usando VB
Console.WriteLine("\nCreating object: VBDerived");
objects[2] = new VBDerived();
// Chiama il metodo virtuale di ogni oggetto
Console.WriteLine("\nCalling Methods");
foreach(VCBase obj in objects){
obj.Method();
}
// Test sull'eccezione
try{
(objects[2] as VBDerived).AnotherMethodThatThrows();
}catch(ApplicationException){
// Risponde al fallimento
}
}
}
CrossLang.cs darà forma all'assembly eseguibile. Per prima cosa viene creato un array nel quale saranno caricati gli oggetti creati sulla base di quelli definiti nei vari sorgenti presentati. In posizione 0 viene caricato l'oggetto creato a partire da ILDerived. Essendo l'oggetto derivato da VBDerived a sua volta discendente da VCBase i relativi "Constructor" saranno richiamati dando luogo all'output: Creating object: ILDerived Executing the VCBase::VCBase() constructor Executing the VBDerived.New() constructor Executing the ILDerived::ctor() constructor Analogamente, in posizione 1 dell'array è caricato l'oggetto creato da CSDerived, derivato da ILDerived derivato da VBDerived a sua volta ancora discendente da VCBase. L'output su console in questo caso risulta: Creating object: CSDerived
Executing the VCBase::VCBase() constructor
Executing the VBDerived.New() constructor
Executing the ILDerived::ctor() constructor
Executing the CSDerived.CSDerived() constructor
Infine da VBDerived è creato l'oggetto posto nell'ultima locazione dell'array, ed essendo derivato direttamente da VCBase genera: Creating object: VBDerived Executing the VCBase::VCBase() constructor Executing the VBDerived.New() constructor A questo punto mediante foreach, che permette di scorrere un array (trattato separatamente in questo tutorial) il metodo virtuale presente in ogni oggetto viene eseguito: Calling Methods Executing the ILDerived::Method() virtual method Executing the CSDerived.Method() virtual method Executing the VBDerived.Method() virtual method
Fonti: Documentazione .NET Framework SDK |