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