宣告結構類型時請使用ref修飾符。 你在堆疊中分配某個 ref struct 類型的實例,它們無法逃逸到受管理堆。 為確保此特性,編譯器會限制型別的使用 ref struct 如下:
- 你不能用 a
ref struct作為陣列的元素類型。 - 你不能宣告 a
ref struct作為類別中欄位的類型,或非ref struct。 - 你不能把 a
ref struct或 System.ValueTypeSystem.Object打包。 - 你無法在 lambda 表達式或局部函式中捕捉
ref struct變數。 - 在 C# 13 之前,你不能在方法中使用
ref structasync變數。 從 C# 13 開始,ref struct變數不能用於await方法中async表達式的相同區塊中。 但是您可以在同步方法中使用ref struct變數,例如,用在傳回 Task 或 Task<TResult> 的方法中。 - 在 C# 13 之前,你不能在迭代器中使用變
ref struct數。 從 C# 13 開始,可以在迭代器中使用ref struct類型和ref區域變數,前提是其不在yield return陳述式的程式碼區段中。 - 在 C# 13 之前,
ref struct無法實作介面。 從 C# 13 開始,ref結構可以實作介面,但必須遵守 ref 安全規則。 例如,ref struct型別無法轉換成介面型別,因為需要 Boxing 轉換。 - 在 C# 13 之前,
ref struct不能是型別引數。 從 C# 13 開始,當型別參數在其ref struct子句中指定allows ref struct時,where可以是型別引數。
C# 語言參考資料記錄了 C# 語言最新版本。 同時也包含即將推出語言版本公開預覽功能的初步文件。
文件中標示了語言最近三個版本或目前公開預覽版中首次引入的任何功能。
小提示
欲查詢某功能何時首次在 C# 中引入,請參閱 C# 語言版本歷史的條目。
一般而言,當您需要也包含 ref struct 類型的資料成員之類型時,要定義 ref struct 類型:
public ref struct CustomRef
{
public bool IsValid;
public Span<int> Inputs;
public Span<int> Outputs;
}
若要將 ref struct 宣告為 readonly,請在型別宣告中合併 readonly 和 ref 修飾詞 (readonly 修飾詞必須位於 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; }
}
在 NET 中,ref struct 的範例為 System.Span<T> 和 System.ReadOnlySpan<T>。
ref 欄位
你可以宣告 ref 一個欄位, ref struct如下範例所示:
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;
}
}
ref 欄位的值可能為 null。 使用 Unsafe.IsNullRef<T>(T) 方法可判斷 ref 欄位是否為 null。
您可用下列方式,對 readonly 欄位套用 ref 修飾詞:
-
readonly ref: 你可以只在建構子或initaccessor 中使用運算= ref子來重新指派這個欄位。 您可以利用欄位存取修飾詞,在允許的任何時間點,使用=運算子來指派值。 -
ref readonly: 在任何時候,你都無法用運算子為這個欄位指派值=。 不過,你可以用= ref運算元來重新指派欄位。 -
readonly ref readonly: 你只能在建構子或initaccessor 中重新指派此欄位。 您任何時間點都無法對欄位指派值。
編譯器可確保儲存在 ref 欄位中的參考不會比其所參考的值存留更久。
ref 欄位功能可讓您安全實作類型,例如 System.Span<T>:
public readonly ref struct Span<T>
{
internal readonly ref T _reference;
private readonly int _length;
// Omitted for brevity...
}
Span<T> 類型會儲存參考,以透過參考來存取記憶體中的連續元素。 透過使用參考,實 Span<T> 例避免複製它所指的儲存。
可處置模式
您可以定義可處置的 ref struct。 若要這樣做,請確定 ref struct 符合可處置模式。 也就是說,它有一個可存取、無參數且具有Dispose傳回類型的實例void方法。 您可以使用 using 陳述式或宣告,搭配可處置 ref struct 的執行個體。
從 C# 13 開始,您也可以在 IDisposable 型別上實作 ref struct。 不過,多載解析偏好介面方法的可處置模式。 只有在找不到適當的IDisposable.Dispose方法時,編譯程式才會解析為 Dispose 方法。
實作介面的 ref struct 型別限制
這些限制確保 ref struct 實作介面的型別遵循必要的 參考安全 規則。
- 你無法將 a
ref struct轉換成它實作的介面實例。 這個限制包括當你使用型ref struct態作為參數且參數是介面型態時,隱含的轉換。 轉換會導致 Boxing 轉換,這違反了 ref 安全。ref struct可以將方法宣告為明確的介面宣告。 不過,你只能從類型allows ref struct參數型別的通用方法存取這些方法。 - 實作介面 的
ref struct必須 實作所有實例介面成員。 即使介面包含預設實作,ref struct也必須實作實例成員。
編譯器會強制執行這些限制。 如果您撰寫實作介面的 ref struct 型別,則每個新的更新都可能包括新的預設介面成員。 除非你提供任何新實例方法的實作,否則你的應用程式不會編譯。 您無法為具有預設實作的 static 介面方法提供特定的實作。
重要
實作帶有 ref struct 型別的介面,可能會帶來日後破壞原始碼和破壞二進位的變更。 若 a ref struct 實作了另一個組件中定義的介面,而該組件提供了更新,將預設成員加入該介面,則會發生中斷。
原始碼中斷發生在你重新編譯 : ref struct它必須實作新成員時,即使有預設實作。
二進位中斷發生在你升級外部組合語言卻沒有重新編譯型別,ref struct且更新後的程式碼會呼叫新方法的預設實作。 存取預設成員時,執行階段會擲回例外狀況。
C# 語言規格
如需詳細資訊,請參閱 C# 語言規格的下列幾節:
如需 ref 欄位的詳細資訊,請參閱低階結構改善提案附註。