Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Tipi struttura
Usare il ref modificatore per dichiarare un tipo di struttura. Le istanze di un ref struct tipo vengono allocate nello stack e non possono passare all'heap gestito. Per garantire questa proprietà, il compilatore limita l'utilizzo dei ref struct tipi come indicato di seguito:
- Non è possibile usare come
ref structtipo di elemento di una matrice. - Non è possibile dichiarare come
ref structtipo di un campo in una classe o nonref struct. - Non è possibile eseguire una casella a
ref structSystem.ValueType o System.Object. - Non è possibile acquisire una
ref structvariabile in un'espressione lambda o in una funzione locale. - Prima di C# 13, non è possibile usare
ref structvariabili in unasyncmetodo. A partire da C# 13, non è possibile usare una variabileref structnello stesso blocco dell'espressioneawaitin un metodoasync. Tuttavia, è possibile usare le variabiliref structnei metodi sincroni, ad esempio nei metodi che restituiscono Task o Task<TResult>. - Prima di C# 13, non è possibile usare una
ref structvariabile negli iteratori. A partire da C# 13, i tipiref structe le variabili localirefpossono essere usati negli iteratori, purché non si tratti di segmenti di codice con l'istruzioneyield return. - Prima di C# 13,
ref structnon può implementare interfacce. A partire da C# 13, uno structrefpuò implementare le interfacce, ma deve rispettare le regole di sicurezza di riferimento. Ad esempio, un tiporef structnon può essere convertito in un tipo di interfaccia perché richiede una conversione boxing. - Prima di C# 13, un tipo
ref structnon può essere un argomento di tipo. A partire da C# 13, un tiporef structpuò essere l'argomento di tipo quando il parametro di tipo specificaallows ref structnella clausolawhere.
Il riferimento al linguaggio C# documenta la versione rilasciata più di recente del linguaggio C#. Contiene anche la documentazione iniziale per le funzionalità nelle anteprime pubbliche per la versione futura del linguaggio.
La documentazione identifica tutte le funzionalità introdotte nelle ultime tre versioni della lingua o nelle anteprime pubbliche correnti.
Suggerimento
Per trovare quando una funzionalità è stata introdotta per la prima volta in C#, vedere l'articolo sulla cronologia delle versioni del linguaggio C#.
In genere, un tipo ref struct viene definito quando è necessario un tipo che includa anche membri dati di tipi ref struct:
public ref struct CustomRef
{
public bool IsValid;
public Span<int> Inputs;
public Span<int> Outputs;
}
Per dichiarare un tipo ref struct come readonly, combinare i modificatori readonly e ref nella dichiarazione di tipo (il modificatore readonly deve precedere il modificatore ref):
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 gli esempi di un tipo ref struct sono System.Span<T> e System.ReadOnlySpan<T>.
Campi ref
È possibile dichiarare un ref campo in un ref structoggetto , come illustrato nell'esempio seguente:
public ref struct RefFieldExample
{
private ref int number;
public int GetNumber()
{
if (System.Runtime.CompilerServices.Unsafe.IsNullRef(ref number))
{
throw new InvalidOperationException("The number ref field is not initialized.");
}
return number;
}
}
Un campo ref può avere il valore null. Usare il metodo Unsafe.IsNullRef<T>(T) per determinare se un campo ref è null.
È possibile applicare il modificatore readonly a un campo ref nei modi seguenti:
-
readonly ref: è possibile riassegnare questo campo usando l'operatore= refsolo all'interno di un costruttore o di unainitfunzione di accesso. È possibile assegnare un valore con l'operatore=in qualsiasi punto consentito dal modificatore di accesso al campo. -
ref readonly: in qualsiasi momento, non è possibile assegnare un valore con l'operatore=a questo campo. Tuttavia, è possibile riassegnare nuovamente il campo usando l'operatore= ref. -
readonly ref readonly: è possibile riassegnare questo campo solo in un costruttore o in unainitfunzione di accesso. In qualsiasi momento, non è possibile assegnare un valore al campo.
Il compilatore garantisce che un riferimento archiviato in un campo ref non sopravviva al suo referente.
La funzionalità dei campi ref consente un'implementazione sicura dei tipi come System.Span<T>:
public readonly ref struct Span<T>
{
internal readonly ref T _reference;
private readonly int _length;
// Omitted for brevity...
}
Il tipo Span<T> archivia un riferimento tramite il quale accede agli elementi contigui in memoria. Usando un riferimento, un'istanza Span<T> evita di copiare l'archiviazione a cui fa riferimento.
Modello eliminabile
È possibile definire un tipo ref struct eliminabile. A tale scopo, assicurarsi che un tipo ref struct corrisponda al criterio eliminabile. Ovvero, ha un metodo di istanza Dispose accessibile, senza parametri e ha un void tipo restituito. È possibile usare l'istruzione o la dichiarazione using con un'istanza di un tipo ref struct eliminabile.
A partire da C# 13, è anche possibile implementare IDisposable nei tipi ref struct. Tuttavia, la risoluzione dell'overload preferisce il modello eliminabile al metodo di interfaccia. Il compilatore viene risolto in un IDisposable.Dispose metodo solo quando non viene trovato un metodo appropriato Dispose .
Restrizioni per i tipi ref struct che implementano un'interfaccia
Queste restrizioni assicurano che un ref struct tipo che implementa un'interfaccia segua le regole di sicurezza di riferimento necessarie.
- Non è possibile convertire un oggetto in un'istanza
ref structdi un'interfaccia implementata. Questa restrizione include la conversione implicita quando si usa unref structtipo come argomento e il parametro è un tipo di interfaccia. La conversione comporta una conversione boxing, che viola la sicurezza di riferimento. Unref structpuò dichiarare metodi come dichiarazioni di interfaccia esplicite. Tuttavia, è possibile accedere a tali metodi solo da metodi generici in cui i tipi di parametroallows ref structdi tipo. - Un
ref structche implementa un'interfaccia deve implementare tutti i membri dell'istanza dell'interfaccia. Ilref structdeve implementare i membri dell'istanza anche quando l'interfaccia include un'implementazione predefinita.
Il compilatore applica tali restrizioni. Se si scrivono tipi ref struct che implementano interfacce, ogni nuovo aggiornamento potrebbe includere nuovi membri dell'interfaccia predefiniti. Finché non si fornisce un'implementazione per qualsiasi nuovo metodo di istanza, l'applicazione non viene compilata. Non è possibile fornire un'implementazione specifica per un metodo di interfaccia static con un'implementazione predefinita.
Importante
L'implementazione di un'interfaccia con un ref struct tipo introduce la possibilità di apportare modifiche di rilievo di origine e binarie successive. L'interruzione si verifica se un ref struct implementa un'interfaccia definita in un altro assembly e tale assembly fornisce un aggiornamento che aggiunge membri predefiniti a tale interfaccia.
L'interruzione di origine si verifica quando si ricompila : ref structdeve implementare il nuovo membro, anche se è presente un'implementazione predefinita.
L'interruzione binaria si verifica se si aggiorna l'assembly esterno senza ricompilare il ref struct tipo e il codice aggiornato chiama l'implementazione predefinita del nuovo metodo. Il runtime genera un'eccezione quando si accede al membro predefinito.
Specifiche del linguaggio C#
Per altre informazioni, vedere le sezioni seguenti delle specifiche del linguaggio C#:
Per altre informazioni sui campi ref, vedere la nota nella proposta Miglioramenti dello struct di basso livello.