Creare dati incapsulati con struct in C#

Completato

Lavorando al progetto per tenere traccia dei dettagli dell'ordine, è necessario un modo per mantenere le informazioni correlate, ad esempio il nome del cliente, l'indirizzo di spedizione e il totale dell'ordine insieme. Gli struct in C# consentono di creare un contenitore incapsulato di base per questi dati, semplificando l'uso e il passaggio come singola unità.

Informazioni sugli struct

Gli struct sono tipi valore in C#, ovvero archiviano direttamente i dati anziché farvi riferimento. Usare la struct parola chiave per definire uno struct. Gli struct vengono in genere usati per tipi di dati di piccole dimensioni che offrono un comportamento minimo.

  • Gli struct hanno una semantica di valori, ovvero i relativi valori vengono copiati durante le chiamate di assegnazione o metodo.
  • I casi d'uso comuni includono la rappresentazione di numeri, valori booleani, caratteri e istanze temporali.
  • Gli struct vengono comunemente usati per rappresentare dati leggeri come forme geometriche (ad esempio, Rectangle, Circle), coordinate o impostazioni di configurazione.

Gli struct sono più adatti per dati di piccole dimensioni, non modificabili e critici per le prestazioni. Per oggetti più grandi e più complessi o quando il comportamento è attivo, è consigliabile usare le classi. A differenza delle classi, gli struct non possono ereditare da altri struct o classi, ma possono implementare interfacce.

Suggerimento

Se il tipo è incentrato sul comportamento anziché sui dati, le classi sono spesso una scelta migliore a causa della semantica di riferimento.

Definire e implementare uno struct

public struct Point
{
    public int X;
    public int Y;

    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}

L'esempio di codice illustra come definire uno struct con campi e un costruttore in C#.

Gli struct possono anche implementare interfacce, ma non possono ereditare da altre classi o struct.

Incapsulare i dati con struct

L'incapsulamento consente di controllare l'accesso ai dati all'interno di uno struct. Usare i modificatori di accesso come private, publico internal per specificare l'accessibilità.

  • I campi e le proprietà possono essere resi privati per limitare l'accesso diretto.
  • I metodi possono fornire modi controllati per interagire con i dati.

Per esempio:

public struct Rectangle
{
    private int width;
    private int height;

    public Rectangle(int width, int height)
    {
        this.width = width;
        this.height = height;
    }

    public int Area => width * height;
}

L'esempio di codice illustra uno struct in C# con campi incapsulati e una proprietà calcolata per l'area.

Applicare il modificatore readonly agli struct per l'immutabilità

L'immutabilità garantisce che una volta creato uno struct, i dati non possono essere modificati. Uno struct è utile quando si utilizzano dati che devono rimanere costanti per tutta la durata, ad esempio coordinate o valori di configurazione. Quando si applica il modificatore a uno struct, è possibile applicare l'immutabilità, rendendo il readonly codice più prevedibile e meno soggetto a errori causati da modifiche impreviste.

public readonly struct ImmutablePoint
{
    public int X { get; init; }
    public int Y { get; init; }

    public ImmutablePoint(int x, int y)
    {
        X = x;
        Y = y;
    }
}

L'esempio di codice illustra l'uso del readonly modificatore per creare uno struct non modificabile in C#.

Nota

Anche se lo struct stesso non è modificabile, i tipi riferimento modificabili all'interno di esso possono comunque cambiare lo stato.

Usare gli inizializzatori di oggetti con struct

Quando si usano gli struct, spesso è necessario inizializzare più proprietà. Gli inizializzatori di oggetti offrono un modo semplice e leggibile per creare e inizializzare istanze di struct in un unico passaggio. Questo approccio riduce il codice ripetitivo e rende chiara la finalità.

L'esempio di codice seguente definisce uno struct con proprietà che raggruppano i dati correlati e semplificano l'inizializzazione e l'uso delle istanze dello struct.

public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

Usando un inizializzatore di oggetti, è possibile creare e inizializzare un Pointoggetto :

var point = new Point { X = 10, Y = 20 };

Nell'esempio di codice viene illustrato come usare un inizializzatore di oggetto per impostare i valori delle proprietà durante la creazione di un'istanza di struct.

Suggerimento

Gli inizializzatori di oggetti rendono il codice più conciso e più facile da leggere quando si usano struct con più proprietà.

Esempio pratico: Uso di struct per rappresentare i punti nello spazio 2D

Gli struct vengono spesso usati per rappresentare strutture di dati di piccole dimensioni non modificabili. Ad esempio, è possibile usare uno struct per rappresentare un punto nello spazio 2D e calcolare la distanza tra due punti:

public struct Point
{
    public int X { get; }
    public int Y { get; }

    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }

    public double DistanceTo(Point other)
    {
        int dx = X - other.X;
        int dy = Y - other.Y;
        return Math.Sqrt(dx * dx + dy * dy);
    }
}

var point1 = new Point(3, 4);
var point2 = new Point(7, 1);
Console.WriteLine($"Distance between points: {point1.DistanceTo(point2)}");

In questo esempio viene illustrato come definire uno struct per un punto, calcolare la distanza tra due punti e usare lo struct in un semplice programma.

La combinazione di incapsulamento, immutabilità e inizializzatori di oggetto consente di creare struct efficienti e prevedibili. Queste funzionalità consentono di gestire i dati correlati in modo pulito e organizzato.