Cenni preliminari sul sistema di tipi comuni
Aggiornamento: novembre 2007
In questa sezione vengono descritti i concetti e i termini utili per comprendere e lavorare con l'implementazione del linguaggio del sistema di tipi comuni.
Classificazione dei tipi
Il sistema di tipi comuni supporta due categorie generali di tipi, ciascuna delle quali è a sua volta suddivisa in sottocategorie:
Tipi di valore
I tipi di valore contengono direttamente i relativi dati; le istanze dei tipi di valore sono allocate sullo stack oppure inline in una struttura. I tipi di valore possono essere incorporati, ovvero implementati dal runtime, definiti dall'utente, oppure essere enumerazioni. Per un elenco dei tipi di valore incorporati, vedere la libreria di classi .NET Framework.
Tipi di riferimento
I tipi di riferimento consentono di memorizzare un riferimento all'indirizzo di memoria del valore e sono allocati sull'heap. I tipi di riferimento possono essere autodescrittivi, di puntatore o di interfaccia. Il tipo di un tipo di riferimento può essere determinato a partire dai valori dei tipi autodescrittivi. I tipi autodescrittivi sono a loro volta suddivisi in matrici e tipi di classi. I tipi di classi sono classi definite dall'utente, tipi di valore boxed e delegati.
Le variabili che sono tipi di valore contengono ciascuna una propria copia dei dati; di conseguenza le operazioni su una variabile non hanno effetto sulle altre. Le variabili che sono tipi di riferimento possono fare riferimento a uno stesso oggetto; di conseguenza le operazioni su una variabile hanno effetto sullo stesso oggetto cui un'altra variabile fa riferimento.
Tutti i tipi derivano dal tipo di base System.Object.
Nell'esempio che segue viene illustrata la differenza tra i tipi di riferimento e i tipi di valore.
Class Class1
Public Value As Integer = 0
End Class 'Class1
Class Test
Shared Sub Main()
Dim val1 As Integer = 0
Dim val2 As Integer = val1
val2 = 123
Dim ref1 As New Class1()
Dim ref2 As Class1 = ref1
ref2.Value = 123
Console.WriteLine("Values: {0}, {1}", val1, val2)
Console.WriteLine("Refs: {0}, {1}", ref1.Value, ref2.Value)
End Sub 'Main
End Class 'Test
using System;
class Class1
{
public int Value = 0;
}
class Test
{
static void Main() {
int val1 = 0;
int val2 = val1;
val2 = 123;
Class1 ref1 = new Class1();
Class1 ref2 = ref1;
ref2.Value = 123;
Console.WriteLine("Values: {0}, {1}", val1, val2);
Console.WriteLine("Refs: {0}, {1}", ref1.Value, ref2.Value);
}
}
L'output del programma è il seguente:
Values: 0, 123
Refs: 123, 123
Nel diagramma che segue sono mostrate le correlazioni tra i diversi tipi. Si noti che le istanze dei tipi possono essere semplicemente tipi di valore o tipi autodescrittivi, anche se esistono sottocategorie di tali tipi.
Classificazione dei tipi
Per ulteriori informazioni su ciascun tipo, vedere: tipi di valore, enumerazioni, classi, delegati, matrici, interfacce e puntatori.
Valori e oggetti
I valori sono rappresentazioni binarie di dati, e i tipi forniscono un modo di interpretare i dati. Un tipo di valore viene memorizzato direttamente come rappresentazione binaria dei dati del tipo. Il valore di un tipo di riferimento è il percorso della sequenza di bit che rappresenta i dati del tipo.
Ogni valore contiene un tipo preciso che definisce completamente la rappresentazione del valore e le operazioni definite sul valore. I valori dei tipi autodescrittivi sono detti oggetti. Mentre è sempre possibile determinare il tipo esatto di un oggetto esaminandone il valore, non è possibile farlo con un tipo di valore o un tipo di puntatore. Un valore può avere più di un tipo. Un valore di un tipo utilizzato per implementare un'interfaccia è anche un valore di quel tipo di interfaccia. Analogamente, un valore di un tipo che deriva da un tipo base è anche un valore di quel tipo base.
Tipi e assembly
Il runtime utilizza gli assembly per individuare e caricare i tipi. Il manifesto assembly contiene le informazioni utilizzate dal runtime per risolvere tutti i riferimenti ai tipi eseguiti all'interno dell'area di validità dell'assembly.
Un nome di tipo nel runtime comprende due parti logiche: il nome dell'assembly e il nome del tipo all'interno dell'assembly. Due tipi con lo stesso nome ma in assembly diversi sono definiti come due tipi distinti.
Gli assembly garantiscono la coerenza tra l'area di validità dei nomi vista dallo sviluppatore e l'area di validità dei nomi vista dal sistema di runtime. Gli sviluppatori modificano i tipi nel contesto di un assembly. Il contenuto dell'assembly creato dallo sviluppatore definisce l'area di validità dei nomi che saranno disponibili in fase di esecuzione.
Tipi e spazi dei nomi
Dal punto di visto del runtime, uno spazio dei nomi è semplicemente un insieme di nomi dei tipi. Linguaggi particolari possono avere costrutti e corrispondente sintassi che consentono agli sviluppatori di formare gruppi logici di tipi, ma tali costrutti non sono utilizzati dal runtime nell'associazione dei tipi. Di conseguenza sia la classe Object che la classe String fanno parte dello spazio dei nomi System, ma il runtime riconosce solo i nomi completi di ciascun tipo, ovvero, rispettivamente, System.Object e System.String.
È possibile compilare un singolo assembly che espone i tipi che sembrano provenire da due spazi dei nomi gerarchici diversi, come System.Collections e System.Windows.Forms. È inoltre possibile creare due assembly che esportano entrambi i tipi i cui nomi contengono MyDll.MyClass.
Se si crea uno strumento per rappresentare i tipi in un assembly come appartenenti a uno spazio dei nomi gerarchico, lo strumento deve enumerare i tipi in un assembly o in un gruppo di assembly e analizzare i nomi dei tipi per derivarne una relazione gerarchica.
Vedere anche
Concetti
Cenni preliminari sulla libreria di classi .NET Framework
Specifiche CLS (Common Language Specification)
Altre risorse
Assembly in Common Language Runtime