Tipi di struttura (riferimenti per C#)Structure types (C# reference)

Un tipo di struttura o un tipo di struct è un tipo valore che può incapsulare dati e funzionalità correlate.A structure type (or struct type) is a value type that can encapsulate data and related functionality. Usare la struct parola chiave per definire un tipo di struttura:You use the struct keyword to define a structure type:

public struct Coords
{
    public Coords(double x, double y)
    {
        X = x;
        Y = y;
    }

    public double X { get; }
    public double Y { get; }

    public override string ToString() => $"({X}, {Y})";
}

I tipi di struttura hanno una semantica di valori.Structure types have value semantics. Ovvero una variabile di un tipo di struttura contiene un'istanza del tipo.That is, a variable of a structure type contains an instance of the type. Per impostazione predefinita, i valori delle variabili vengono copiati durante l'assegnazione, passando un argomento a un metodo e restituendo il risultato di un metodo.By default, variable values are copied on assignment, passing an argument to a method, and returning a method result. Nel caso di una variabile di tipo struttura, viene copiata un'istanza del tipo.In the case of a structure-type variable, an instance of the type is copied. Per ulteriori informazioni, vedere tipi di valore.For more information, see Value types.

In genere, i tipi di struttura vengono utilizzati per progettare piccoli tipi incentrati sui dati che forniscono un comportamento minimo o nullo.Typically, you use structure types to design small data-centric types that provide little or no behavior. .NET, ad esempio, USA i tipi di struttura per rappresentare un numero (sia Integer che Real), un valore booleano, un carattere Unicode, un' istanza temporale.For example, .NET uses structure types to represent a number (both integer and real), a Boolean value, a Unicode character, a time instance. Se si è interessati al comportamento di un tipo, è consigliabile definire una classe.If you're focused on the behavior of a type, consider defining a class. I tipi di classe hanno una semantica di riferimento.Class types have reference semantics. Ovvero una variabile di un tipo di classe contiene un riferimento a un'istanza del tipo, non l'istanza stessa.That is, a variable of a class type contains a reference to an instance of the type, not the instance itself.

Poiché i tipi di struttura hanno una semantica di valori, è consigliabile definire tipi di struttura non modificabili .Because structure types have value semantics, we recommend you to define immutable structure types.

readonly structreadonly struct

A partire da C# 7,2, è possibile usare il readonly modificatore per dichiarare che un tipo di struttura non è modificabile.Beginning with C# 7.2, you use the readonly modifier to declare that a structure type is immutable. Tutti i membri dati di uno readonly struct devono essere di sola lettura, come indicato di seguito:All data members of a readonly struct must be read-only as follows:

  • Qualsiasi dichiarazione di campo deve avere il readonly modificatoreAny field declaration must have the readonly modifier
  • Qualsiasi proprietà, inclusa quella implementata automaticamente, deve essere di sola lettura.Any property, including auto-implemented ones, must be read-only. In C# 9,0 e versioni successive, una proprietà può avere una init funzione di accesso.In C# 9.0 and later, a property may have an init accessor.

Ciò garantisce che nessun membro di uno readonly struct modifichi lo stato dello struct.That guarantees that no member of a readonly struct modifies the state of the struct. In C# 8,0 e versioni successive, ciò significa che altri membri di istanza eccetto i costruttori sono implicitamente readonly .In C# 8.0 and later, that means that other instance members except constructors are implicitly readonly.

Nota

In uno readonly struct un membro dati di un tipo di riferimento modificabile può ancora mutare il proprio stato.In a readonly struct, a data member of a mutable reference type still can mutate its own state. Ad esempio, non è possibile sostituire un' List<T> istanza, ma è possibile aggiungervi nuovi elementi.For example, you can't replace a List<T> instance, but you can add new elements to it.

Il codice seguente definisce uno readonly struct con Setter di proprietà solo init, disponibile in C# 9,0 e versioni successive:The following code defines a readonly struct with init-only property setters, available in C# 9.0 and later:

public readonly struct Coords
{
    public Coords(double x, double y)
    {
        X = x;
        Y = y;
    }

    public double X { get; init; }
    public double Y { get; init; }

    public override string ToString() => $"({X}, {Y})";
}

readonly membri di istanzareadonly instance members

A partire da C# 8,0, è anche possibile usare il readonly modificatore per dichiarare che un membro di istanza non modifica lo stato di uno struct.Beginning with C# 8.0, you can also use the readonly modifier to declare that an instance member doesn't modify the state of a struct. Se non è possibile dichiarare l'intero tipo di struttura come readonly , usare il readonly modificatore per contrassegnare i membri di istanza che non modificano lo stato dello struct.If you can't declare the whole structure type as readonly, use the readonly modifier to mark the instance members that don't modify the state of the struct.

All'interno di un readonly membro di istanza non è possibile assegnare ai campi di istanza della struttura.Within a readonly instance member, you can't assign to structure's instance fields. Tuttavia, un readonly membro può chiamare un membro non readonly .However, a readonly member can call a non-readonly member. In tal caso, il compilatore crea una copia dell'istanza della struttura e chiama il non readonly membro sulla copia.In that case the compiler creates a copy of the structure instance and calls the non-readonly member on that copy. Di conseguenza, l'istanza della struttura originale non viene modificata.As a result, the original structure instance is not modified.

In genere, il readonly modificatore viene applicato ai tipi di membri di istanza seguenti:Typically, you apply the readonly modifier to the following kinds of instance members:

  • Metodimethods:

    public readonly double Sum()
    {
        return X + Y;
    }
    

    È anche possibile applicare il readonly modificatore ai metodi che eseguono l'override dei metodi dichiarati in System.Object :You can also apply the readonly modifier to methods that override methods declared in System.Object:

    public readonly override string ToString() => $"({X}, {Y})";
    
  • Proprietà e indicizzatori:properties and indexers:

    private int counter;
    public int Counter
    {
        readonly get => counter;
        set => counter = value;
    }
    

    Se è necessario applicare il readonly modificatore a entrambe le funzioni di accesso di una proprietà o un indicizzatore, applicarlo nella dichiarazione della proprietà o dell'indicizzatore.If you need to apply the readonly modifier to both accessors of a property or indexer, apply it in the declaration of the property or indexer.

    Nota

    Il compilatore dichiara una get funzione di accesso di una proprietà implementata automaticamente come readonly , indipendentemente dalla presenza del readonly modificatore in una dichiarazione di proprietà.The compiler declares a get accessor of an auto-implemented property as readonly, regardless of presence of the readonly modifier in a property declaration.

    In C# 9,0 e versioni successive, è possibile applicare il readonly modificatore a una proprietà o a un indicizzatore con una init funzione di accesso:In C# 9.0 and later, you may apply the readonly modifier to a property or indexer with an init accessor:

    public readonly double X { get; init; }
    

Non è possibile applicare il readonly modificatore ai membri statici di un tipo di struttura.You can't apply the readonly modifier to static members of a structure type.

Il compilatore può utilizzare il readonly modificatore per le ottimizzazioni delle prestazioni.The compiler may make use of the readonly modifier for performance optimizations. Per altre informazioni, vedere scrivere codice C# sicuro ed efficiente.For more information, see Write safe and efficient C# code.

Limitazioni con la progettazione di un tipo di strutturaLimitations with the design of a structure type

Quando si progetta un tipo di struttura, si hanno le stesse funzionalità di un tipo di classe , con le eccezioni seguenti:When you design a structure type, you have the same capabilities as with a class type, with the following exceptions:

  • Non è possibile dichiarare un costruttore senza parametri.You can't declare a parameterless constructor. Ogni tipo di struttura fornisce già un costruttore senza parametri implicito che produce il valore predefinito del tipo.Every structure type already provides an implicit parameterless constructor that produces the default value of the type.

  • Non è possibile inizializzare una proprietà o un campo di istanza in corrispondenza della relativa dichiarazione.You can't initialize an instance field or property at its declaration. Tuttavia, è possibile inizializzare un campo statico o const o una proprietà statica alla relativa dichiarazione.However, you can initialize a static or const field or a static property at its declaration.

  • Un costruttore di un tipo di struttura deve inizializzare tutti i campi di istanza del tipo.A constructor of a structure type must initialize all instance fields of the type.

  • Un tipo di struttura non può ereditare da un altro tipo di classe o struttura e non può essere la base di una classe.A structure type can't inherit from other class or structure type and it can't be the base of a class. Tuttavia, un tipo di struttura può implementare le interfacce.However, a structure type can implement interfaces.

  • Non è possibile dichiarare un finalizzatore all'interno di un tipo di struttura.You can't declare a finalizer within a structure type.

Creazione di un'istanza di un tipo di strutturaInstantiation of a structure type

In C# è necessario inizializzare una variabile dichiarata prima di poterla usare.In C#, you must initialize a declared variable before it can be used. Poiché una variabile di tipo struttura non può essere null (a meno che non sia una variabile di un tipo di valore Nullable), è necessario creare un'istanza del tipo corrispondente.Because a structure-type variable can't be null (unless it's a variable of a nullable value type), you must instantiate an instance of the corresponding type. Esistono diversi modi per eseguire questa operazione.There are several ways to do that.

In genere, si crea un'istanza di un tipo di struttura chiamando un costruttore appropriato con l' new operatore.Typically, you instantiate a structure type by calling an appropriate constructor with the new operator. Ogni tipo di struttura ha almeno un costruttore.Every structure type has at least one constructor. Si tratta di un costruttore senza parametri implicito che produce il valore predefinito del tipo.That's an implicit parameterless constructor, which produces the default value of the type. È anche possibile usare un' espressione con valore predefinito per produrre il valore predefinito di un tipo.You can also use a default value expression to produce the default value of a type.

Se tutti i campi di istanza di un tipo di struttura sono accessibili, è anche possibile crearne un'istanza senza l' new operatore.If all instance fields of a structure type are accessible, you can also instantiate it without the new operator. In tal caso, è necessario inizializzare tutti i campi di istanza prima del primo utilizzo dell'istanza.In that case you must initialize all instance fields before the first use of the instance. L'esempio seguente illustra come eseguire questa operazione:The following example shows how to do that:

public static class StructWithoutNew
{
    public struct Coords
    {
        public double x;
        public double y;
    }

    public static void Main()
    {
        Coords p;
        p.x = 3;
        p.y = 4;
        Console.WriteLine($"({p.x}, {p.y})");  // output: (3, 4)
    }
}

Nel caso dei tipi valore predefiniti, usare i valori letterali corrispondenti per specificare un valore del tipo.In the case of the built-in value types, use the corresponding literals to specify a value of the type.

Passaggio di variabili di tipo struttura per riferimentoPassing structure-type variables by reference

Quando si passa una variabile di tipo struttura a un metodo come argomento o si restituisce un valore del tipo di struttura da un metodo, viene copiata l'intera istanza di un tipo di struttura.When you pass a structure-type variable to a method as an argument or return a structure-type value from a method, the whole instance of a structure type is copied. Che può influire sulle prestazioni del codice in scenari a prestazioni elevate che coinvolgono tipi di struttura di grandi dimensioni.That can affect the performance of your code in high-performance scenarios that involve large structure types. È possibile evitare la copia dei valori passando una variabile di tipo struttura per riferimento.You can avoid value copying by passing a structure-type variable by reference. Usare i ref out in modificatori di parametro del metodo, o per indicare che un argomento deve essere passato per riferimento.Use the ref, out, or in method parameter modifiers to indicate that an argument must be passed by reference. Usare i riferimenti ref per restituire il risultato di un metodo in base al riferimento.Use ref returns to return a method result by reference. Per altre informazioni, vedere scrivere codice C# sicuro ed efficiente.For more information, see Write safe and efficient C# code.

ref structref struct

A partire da C# 7,2, è possibile usare il ref modificatore nella dichiarazione di un tipo di struttura.Beginning with C# 7.2, you can use the ref modifier in the declaration of a structure type. Le istanze di un ref tipo struct vengono allocate nello stack e non possono essere sottoposte a escape nell'heap gestito.Instances of a ref struct type are allocated on the stack and can't escape to the managed heap. Per assicurarsi che il compilatore limiti l'utilizzo dei ref tipi struct come indicato di seguito:To ensure that, the compiler limits the usage of ref struct types as follows:

  • Uno ref struct non può essere il tipo di elemento di una matrice.A ref struct can't be the element type of an array.
  • Uno ref struct non può essere un tipo dichiarato di un campo di una classe o di un ref non struct.A ref struct can't be a declared type of a field of a class or a non-ref struct.
  • Uno ref struct non può implementare le interfacce.A ref struct can't implement interfaces.
  • Uno ref struct non può essere boxed in System.ValueType o System.Object .A ref struct can't be boxed to System.ValueType or System.Object.
  • Uno ref struct non può essere un argomento di tipo.A ref struct can't be a type argument.
  • Una ref variabile struct non può essere acquisita da un' espressione lambda o da una funzione locale.A ref struct variable can't be captured by a lambda expression or a local function.
  • Una ref variabile struct non può essere usata in un async metodo.A ref struct variable can't be used in an async method. Tuttavia, è possibile usare ref le variabili struct nei metodi sincroni, ad esempio, in quelli che restituiscono Task o Task<TResult> .However, you can use ref struct variables in synchronous methods, for example, in those that return Task or Task<TResult>.
  • refNon è possibile usare una variabile struct negli iteratori.A ref struct variable can't be used in iterators.

In genere, si definisce un ref tipo di struct quando è necessario un tipo che include anche membri dati di ref tipi struct:Typically, you define a ref struct type when you need a type that also includes data members of ref struct types:

public ref struct CustomRef
{
    public bool IsValid;
    public Span<int> Inputs;
    public Span<int> Outputs;
}

Per dichiarare uno ref struct come readonly , combinare i readonly ref modificatori e nella dichiarazione del tipo (il readonly modificatore deve essere prima del ref modificatore):To declare a ref struct as readonly, combine the readonly and ref modifiers in the type declaration (the readonly modifier must come before the ref modifier):

public readonly ref struct ConversionRequest
{
    public ConversionRequest(double rate, ReadOnlySpan<double> values)
    {
        Rate = rate;
        Values = values;
    }

    public double Rate { get; }
    public ReadOnlySpan<double> Values { get; }
}

In .NET, esempi di uno ref struct sono System.Span<T> e System.ReadOnlySpan<T> .In .NET, examples of a ref struct are System.Span<T> and System.ReadOnlySpan<T>.

vincolo structstruct constraint

È anche possibile usare la struct parola chiave nel struct vincolo per specificare che un parametro di tipo è un tipo di valore non nullable.You also use the struct keyword in the struct constraint to specify that a type parameter is a non-nullable value type. I tipi di struttura e di enumerazione soddisfano il struct vincolo.Both structure and enumeration types satisfy the struct constraint.

ConversioniConversions

Per qualsiasi tipo di struttura (ad eccezione dei tipi ref struct ), esistono conversioni Boxing e unboxing da e verso i System.ValueType System.Object tipi e.For any structure type (except ref struct types), there exist boxing and unboxing conversions to and from the System.ValueType and System.Object types. Esistono anche conversioni boxing e unboxing tra un tipo di struttura e qualsiasi interfaccia implementata.There exist also boxing and unboxing conversions between a structure type and any interface that it implements.

Specifiche del linguaggio C#C# language specification

Per ulteriori informazioni, vedere la sezione structs della specifica del linguaggio C#.For more information, see the Structs section of the C# language specification.

Per ulteriori informazioni sulle funzionalità introdotte in C# 7,2 e versioni successive, vedere le note sulla proposta di funzionalità seguenti:For more information about features introduced in C# 7.2 and later, see the following feature proposal notes:

Vedi ancheSee also