Condividi tramite


Structures

Una struttura è un tipo di oggetto compatto che può essere più efficiente di una classe per i tipi con una piccola quantità di dati e un comportamento semplice.

Sintassi

[ attributes ]
type [accessibility-modifier] type-name =
    struct
        type-definition-elements-and-members
    end
// or
[ attributes ]
[<StructAttribute>]
type [accessibility-modifier] type-name =
    type-definition-elements-and-members

Osservazioni:

Le strutture sono tipi valore, il che significa che vengono archiviati direttamente nello stack o, quando vengono usati come campi o elementi di matrice, inline nel tipo padre. A differenza delle classi e dei record, le strutture hanno una semantica pass-by-value. Ciò significa che sono utili principalmente per piccole aggregazioni di dati a cui si accede e che vengono copiati di frequente.

Nella sintassi precedente vengono visualizzate due forme. Il primo non è la sintassi leggera, ma è tuttavia spesso usato perché, quando si usano le struct parole chiave e end , è possibile omettere l'attributo StructAttribute , che viene visualizzato nel secondo modulo. È possibile abbreviare StructAttribute solo Structcon .

I membri type-definition-elements-and-members nella sintassi precedente rappresentano le dichiarazioni e le definizioni dei membri. Le strutture possono avere costruttori e campi modificabili e non modificabili e possono dichiarare membri e implementazioni dell'interfaccia. Per altre informazioni, vedere Membri.

Le strutture non possono partecipare all'ereditarietà, non possono contenere let o do associazioni e non possono contenere in modo ricorsivo campi del proprio tipo (anche se possono contenere celle di riferimento che fanno riferimento al proprio tipo).

Poiché le strutture non consentono let associazioni, è necessario dichiarare i campi nelle strutture usando la val parola chiave . La val parola chiave definisce un campo e il relativo tipo, ma non consente l'inizializzazione. Le dichiarazioni vengono invece val inizializzate su zero o null. Per questo motivo, le strutture con un costruttore implicito ( ovvero i parametri specificati immediatamente dopo il nome della struttura nella dichiarazione) richiedono che val le dichiarazioni vengano annotate con l'attributo DefaultValue . Le strutture con un costruttore definito supportano comunque l'inizializzazione zero. Pertanto, l'attributo DefaultValue è una dichiarazione che tale valore zero è valido per il campo. I costruttori impliciti per le strutture non eseguono azioni perché let e do le associazioni non sono consentite nel tipo, ma i valori dei parametri del costruttore impliciti passati sono disponibili come campi privati.

I costruttori espliciti possono comportare l'inizializzazione dei valori di campo. Quando si dispone di una struttura con un costruttore esplicito, supporta comunque l'inizializzazione zero; Tuttavia, non si usa l'attributo DefaultValue nelle val dichiarazioni perché è in conflitto con il costruttore esplicito. Per altre informazioni sulle val dichiarazioni, vedere Campi espliciti: parola val chiave.

Gli attributi e i modificatori di accessibilità sono consentiti nelle strutture e seguono le stesse regole di quelle per altri tipi. Per altre informazioni, vedere Attributi e controllo di accesso.

Negli esempi di codice seguenti vengono illustrate le definizioni di struttura.

// In Point3D, three immutable values are defined.
// x, y, and z will be initialized to 0.0.
type Point3D =
    struct
        val x: float
        val y: float
        val z: float
    end

// In Point2D, two immutable values are defined.
// It also has a member which computes a distance between itself and another Point2D.
// Point2D has an explicit constructor.
// You can create zero-initialized instances of Point2D, or you can
// pass in arguments to initialize the values.
type Point2D =
    struct
        val X: float
        val Y: float
        new(x: float, y: float) = { X = x; Y = y }

        member this.GetDistanceFrom(p: Point2D) =
            let dX = (p.X - this.X) ** 2.0
            let dY = (p.Y - this.Y) ** 2.0

            dX + dY |> sqrt
    end

Struct ByRefLike

È possibile definire struct personalizzati che possono essere conformi alla semantica simile a byref: vedere Byrefs per altre informazioni. Questa operazione viene eseguita con l'attributo IsByRefLikeAttribute:

open System
open System.Runtime.CompilerServices

[<IsByRefLike; Struct>]
type S(count1: Span<int>, count2: Span<int>) =
    member x.Count1 = count1
    member x.Count2 = count2

IsByRefLike non implica Struct. Entrambi devono essere presenti sul tipo.

Uno struct simile a "byref" in F# è un tipo di valore legato allo stack. Non viene mai allocata nell'heap gestito. Una struttura simile a byrefè utile per la programmazione ad alte prestazioni, in quanto è soggetta a una serie di controlli rigorosi sulla durata e sull'assenza di acquisizione. Le regole sono:

  • Possono essere usati come parametri di funzione, parametri del metodo, variabili locali, metodo restituito.
  • Non possono essere membri statici o di istanza di una classe o di uno struct normale.
  • Non possono essere acquisiti da alcun costrutto di chiusura (async metodi o espressioni lambda).
  • Non possono essere usati come parametro generico.

Anche se queste regole limitano molto fortemente l'utilizzo, lo fanno per soddisfare la promessa di elaborazione ad alte prestazioni in modo sicuro.

Struct ReadOnly

È possibile annotare gli struct con l'attributo IsReadOnlyAttribute . Per esempio:

[<IsReadOnly; Struct>]
type S(count1: int, count2: int) =
    member x.Count1 = count1
    member x.Count2 = count2

IsReadOnly non implica Struct. È necessario aggiungere entrambi per avere uno IsReadOnly struct.

L'uso di questo attributo genera metadati che consentono rispettivamente a F# e C# di considerarlo come inref<'T> e in ref.

La definizione di un valore modificabile all'interno di uno struct readonly genera un errore.

Record struct e unioni discriminate

È possibile rappresentare record e unioni discriminate come struct con l'attributo [<Struct>] . Per altre informazioni, vedere ogni articolo.

Vedere anche