Tipi di valore (riferimenti per C#)
I tipi di valore e i tipi di riferimento sono le due categorie principali di tipi C#. Una variabile di un tipo di valore contiene un'istanza del tipo. Ciò è diverso da una variabile di un tipo di 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 di 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 di valore contiene un membro dati di un tipo di riferimento, viene copiato solo il riferimento all'istanza del tipo di riferimento quando viene copiata un'istanza di tipo valore. Sia la copia che l'istanza 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 di valore non modificabili. Questo articolo usa i tipi di valore modificabili solo a scopo dimostrativo.
Tipi di tipi di valore e vincoli di tipo
Un tipo di valore può essere uno dei due tipi seguenti:
- un tipo di struttura, che incapsula i dati e le funzionalità correlate
- un tipo di enumerazione, definito da un set di costanti denominate e rappresenta una scelta o una combinazione di scelte
Un tipo diT?
valore nullable rappresenta tutti i valori del tipo T
di valore sottostante e un valore Null aggiuntivo. Non è possibile assegnare null
a una variabile di un tipo di valore, a meno che non sia un tipo di valore nullable.
È possibile usare il struct
vincolo per specificare che un parametro di tipo è un tipo di valore non nullable. Entrambi i tipi di struttura ed enumerazione soddisfano il struct
vincolo. È possibile usare System.Enum
in un vincolo di classe di base , noto come vincolo enumerazione, per specificare che un parametro di tipo è un tipo di enumerazione.
Tipi di valore predefiniti
C# fornisce i tipi di 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 cui consentono determinate operazioni aggiuntive:
È possibile usare valori letterali per fornire un valore di un tipo semplice. Ad esempio,
'A'
è un valore letterale del tipochar
e2001
è un valore letterale del tipoint
.È possibile dichiarare costanti dei tipi semplici con la parola chiave const. Non è possibile avere costanti di altri tipi di struttura.
Le espressioni costanti, le cui operandi sono tutte costanti dei tipi semplici, vengono valutate in fase di compilazione.
Una tupla di valore è un tipo di valore, ma non un tipo semplice.
Specifiche del linguaggio C#
Per altre informazioni, vedere le sezioni seguenti delle specifiche del linguaggio C#: