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:

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 tipo char, 2001 è un valore letterale del tipo int ed 12.34m è un valore letterale del tipo decimal.

  • È possibile dichiarare costanti dei tipi semplici con la parola chiave const.
    Ad esempio, è possibile definire const 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#:

Vedi anche