动态

详情 返回 返回

C# 的 ref struct 類型 - 动态 详情

你可以在 struct 的聲明中使用 ref 修飾符。ref struct 類型的實例是在堆棧上分配的,不能轉義到託管堆。為了確保這一點,編譯器將 ref struct 類型的使用限制如下:

  • ref struct 不能是數組的元素類型。
  • ref struct 不能是類或非 ref struct 的字段的聲明類型。
  • ref struct 不能被 boxed 為 System . ValueType 或 System . Object。
  • ref struct 變量不能在 Lambda 表達式或本地函數中捕獲。
  • 在 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 類型轉換為接口類型。
  • 在 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 ( "編號引用字段未初始化。");
                    }

                return number;
            }
    }

ref 字段可以具有 null 值。使用 Unsafe . IsNullRef < T > ( T ) 方法確定 ref 字段是否為 null。

可通過以下方式將 readonly 修飾符應用於 ref 字段:

  • readonly ref:只能在構造函數或初始化訪問器內部使用 = ref 操作符重新分配此類字段。可以在字段訪問修飾符允許的任何位置使用 = 操作符分配值。
  • ref readonly:在任何時候,都不能使用 = 運算符為此類字段賦值。但是,可以使用 = ref 運算符通過 ref 重新賦值字段。
  • readonly ref readonly:只能在構造函數或 init 訪問器中通過 ref 重新賦值此類字段。在任何時候,都不能為字段賦值。

編譯器會確保存儲在 “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 類型作為參數時,則此限制包括隱式轉換。該轉換會導致 boxed 轉換,這違反了 ref 安全性。ref struct 可以將方法聲明為顯式接口聲明。但是,這些方法只能通過類型參數為 allows ref struct 的泛型方法訪問。
  • 實現某個接口的 ref struct 必須實現該接口的所有實例成員。即使該接口包含默認實現,ref struct 也必須實現其實例成員。

編譯程序強制實施這些限制。如果編寫實現接口的 ref struct 類型,則每個新更新都可能包含新的默認接口成員。在為任何新實例方法提供實現之前,應用程序不會編譯。不能為具有默認實現的 static 接口方法提供特定實現。

重要:實現接口的 ref struct 可能會導致後續的源代碼變更和二進制文件變更。如果 ref struct 實現在另一個程序集中定義的接口,並且該程序集提供將默認成員添加到該接口的更新,那麼就會發生這種變更。

重新編譯 ref struct 時會發生 “源斷裂”:即使存在默認實現,它也必須實現新成員。

如果升級外部程序集而不重新編譯 ref struct 類型,並且更新的代碼調用新方法的默認實現,則會發生二進制分離現象。訪問默認成員時,運行時引發異常。

Add a new 评论

Some HTML is okay.