Tipi di valore (riferimenti per C#)
I tipi valore e i tipi riferimento sono le due categorie principali di tipi C#. Una variabile di un tipo valore contiene un'istanza del tipo. Ciò differisce da una variabile di un tipo riferimento, che contiene un riferimento a un'istanza del tipo. Per impostazione predefinita, per l'assegnazione, il passaggio di un argomento a un metodo e la restituzione di un risultato del metodo vengono copiati i valori delle variabili. Nel caso di variabili di tipo valore, le istanze di tipo corrispondenti vengono copiate. L'esempio seguente illustra questo comportamento:
using System;
public struct MutablePoint
{
public int X;
public int Y;
public MutablePoint(int x, int y) => (X, Y) = (x, y);
public override string ToString() => $"({X}, {Y})";
}
public class Program
{
public static void Main()
{
var p1 = new MutablePoint(1, 2);
var p2 = p1;
p2.Y = 200;
Console.WriteLine($"{nameof(p1)} after {nameof(p2)} is modified: {p1}");
Console.WriteLine($"{nameof(p2)}: {p2}");
MutateAndDisplay(p2);
Console.WriteLine($"{nameof(p2)} after passing to a method: {p2}");
}
private static void MutateAndDisplay(MutablePoint p)
{
p.X = 100;
Console.WriteLine($"Point mutated in a method: {p}");
}
}
// Expected output:
// p1 after p2 is modified: (1, 2)
// p2: (1, 200)
// Point mutated in a method: (100, 200)
// p2 after passing to a method: (1, 200)
Come illustrato nell'esempio precedente, le operazioni su una variabile di tipo valore influiscono solo sull'istanza del tipo di valore archiviata nella variabile.
Se un tipo valore contiene un membro dati di un tipo riferimento, viene copiato solo il riferimento all'istanza del tipo di riferimento quando viene copiata un'istanza di tipo valore. Sia l'istanza di copia che di tipo valore originale hanno accesso alla stessa istanza di tipo riferimento. L'esempio seguente illustra questo comportamento:
using System;
using System.Collections.Generic;
public struct TaggedInteger
{
public int Number;
private List<string> tags;
public TaggedInteger(int n)
{
Number = n;
tags = new List<string>();
}
public void AddTag(string tag) => tags.Add(tag);
public override string ToString() => $"{Number} [{string.Join(", ", tags)}]";
}
public class Program
{
public static void Main()
{
var n1 = new TaggedInteger(0);
n1.AddTag("A");
Console.WriteLine(n1); // output: 0 [A]
var n2 = n1;
n2.Number = 7;
n2.AddTag("B");
Console.WriteLine(n1); // output: 0 [A, B]
Console.WriteLine(n2); // output: 7 [A, B]
}
}
Nota
Per rendere il codice meno soggetto a errori e più affidabile, definire e usare tipi valore non modificabili. Questo articolo usa tipi valore modificabili solo a scopo dimostrativo.
Tipologie di tipi valore e vincoli di tipo
Un tipo valore può essere una delle due tipologie seguenti:
- un tipo di struttura, che incapsula i dati e le funzionalità correlate
- un tipo di enumerazione, che è definito da un set di costanti denominate e rappresenta una scelta o una combinazione di scelte
Un tipo valore nullable T?
rappresenta tutti i valori del tipo di valore T
sottostante e un valore Null aggiuntivo. Non è possibile assegnare null
a una variabile di un tipo valore, a meno che non sia un tipo di valore nullable.
È possibile usare il vincolo struct
per specificare che un parametro di tipo è un tipo di valore non nullable. Sia i tipi di struttura che di enumerazione soddisfano il vincolo struct
. È possibile usare System.Enum
in un vincolo di classe di base (noto come vincolo enum) per specificare che un parametro di tipo è un tipo di enumerazione.
Tipi di valore predefiniti
C# fornisce i tipi valore predefiniti seguenti, noti anche come tipi semplici:
- Tipi numerici integrali
- Tipi numerici a virgola mobile
- bool che rappresenta un valore booleano
- char che rappresenta un carattere UTF-16 Unicode
Tutti i tipi semplici sono tipi di struttura e differiscono da altri tipi di struttura in quanto consentono determinate operazioni aggiuntive:
È possibile usare valori letterali per fornire un valore di un tipo semplice.
Ad esempio,'A'
è un valore letterale del tipochar
,2001
è un valore letterale del tipoint
ed12.34m
è un valore letterale del tipodecimal
.È possibile dichiarare costanti dei tipi semplici con la parola chiave const.
Ad esempio, è possibile definireconst decimal = 12.34m
.
Non è possibile avere costanti di altri tipi di struttura.Le espressioni costanti, i cui operandi sono tutte costanti dei tipi semplici, vengono valutate in fase di compilazione.
Una tupla di valori è un tipo valore, ma non un tipo semplice.
Specifiche del linguaggio C#
Per altre informazioni, vedere le sezioni seguenti delle specifiche del linguaggio C#: