ref
結構類型 (C# 參考)
您可以在ref
的宣告中,使用 修飾詞。
ref struct
類型的執行個體,會配置在堆疊上,且無法逸出至受控堆積。 為確保這一點,編譯器對於 ref struct
類型的使用限制如下:
-
ref struct
不能是陣列的元素類型。 -
ref struct
不能是類別或非ref struct
欄位的宣告類型。 - 無法將
ref struct
box 到 System.ValueType 或 System.Object。 -
ref struct
或區域函式無法擷取 變數。 - 在 C# 13 之前,
ref struct
無法在 方法中使用async
變數。 從 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
可以是型別引數。
一般而言,當您需要也包含 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
欄位
從 C# 11 開始,您可以在 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
:只有在建構函式或= ref
內,可以用init
運算子,ref 重新指定這樣的欄位。 您可以利用欄位存取修飾詞,在允許的任何時間點,使用=
運算子來指派值。 -
ref readonly
:您任何時間點都無法對此類欄位指派包含=
運算子的值。 但可以使用= ref
運算子,ref 重新指派欄位。 -
readonly ref readonly
:您只能在建構函式或init
存取子中,重新指派。這樣的欄位。 您任何時間點都無法對欄位指派值。
編譯器可確保儲存在 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
型別遵守必要的 ref 安全規則。
-
ref struct
無法轉換成它所實作之介面的執行個體。 參數若為介面型別,當您使用ref struct
型別作為引數時,此限制會包括隱含轉換。 轉換會導致 Boxing 轉換,這違反了 ref 安全。ref struct
可以將方法宣告為明確的介面宣告。 不過,這些方法只能從擁有類型參數allows ref struct
的泛型方法中存取。 - 實作介面 的
ref struct
必須 實作所有實例介面成員。 即使介面包含預設實作,ref struct
也必須實作實例成員。
編譯器會強制執行這些限制。 如果您撰寫實作介面的 ref struct
型別,則每個新的更新都可能包括新的預設介面成員。 在您提供任何新實例方法的實作之前,您的應用程式將不會編譯。 您無法為具有預設實作的 static
介面方法提供特定的實作。
重要
實作介面的 ref struct
包括後續原始檔中斷和二進位中斷變更的可能性。 如果 ref struct
實作在另一個組件中定義的介面,而且該組件提供將預設成員新增至該介面的更新,即會發生中斷。
當您重新編譯 ref struct
時,會發生源碼中斷:即使有預設的實作,它仍必須實作新的成員。
如果您升級外部組件而不重新編譯 ref struct
型別,而且更新的程式碼會呼叫新方法的預設實作,即會發生二進位中斷。 存取預設成員時,執行階段會擲回例外狀況。
C# 語言規格
如需詳細資訊,請參閱 C# 語言規格的下列幾節:
如需 ref
欄位的詳細資訊,請參閱低階結構改善提案附註。