結構類型 (c # 參考) Structure types (C# reference)

結構類型 (或結構類型) 是可封裝資料和相關功能的實值型別。A structure type (or struct type) is a value type that can encapsulate data and related functionality. 您可以使用 struct 關鍵字來定義結構類型:You use the struct keyword to define a structure type:

public struct Coords
{
    public Coords(double x, double y)
    {
        X = x;
        Y = y;
    }

    public double X { get; }
    public double Y { get; }

    public override string ToString() => $"({X}, {Y})";
}

結構類型具有 值語義Structure types have value semantics. 也就是說,結構型別的變數包含型別的實例。That is, a variable of a structure type contains an instance of the type. 根據預設,變數值會在指派時複製、將引數傳遞至方法,並傳回方法結果。By default, variable values are copied on assignment, passing an argument to a method, and returning a method result. 在結構類型變數的情況下,會複製類型的實例。In the case of a structure-type variable, an instance of the type is copied. 如需詳細資訊,請參閱實 數值型別For more information, see Value types.

一般而言,您會使用結構類型來設計以資料為中心的小型型別,以提供小或無的行為。Typically, you use structure types to design small data-centric types that provide little or no behavior. 例如,.NET 會使用結構類型來表示 整數實數) 的數位 (、 布林值Unicode 字元時間實例For example, .NET uses structure types to represent a number (both integer and real), a Boolean value, a Unicode character, a time instance. 如果您是以類型的行為為焦點,請考慮定義 類別If you're focused on the behavior of a type, consider defining a class. 類別類型具有 參考語義Class types have reference semantics. 也就是說,類別型別的變數包含型別實例的參考,而不是實例本身。That is, a variable of a class type contains a reference to an instance of the type, not the instance itself.

因為結構類型具有值語義,所以建議您定義 不可變 的結構類型。Because structure types have value semantics, we recommend you to define immutable structure types.

readonly 結構readonly struct

從 c # 7.2 開始,您可以使用 readonly 修飾詞來宣告結構類型是不可變的:Beginning with C# 7.2, you use the readonly modifier to declare that a structure type is immutable:

public readonly struct Coords
{
    public Coords(double x, double y)
    {
        X = x;
        Y = y;
    }

    public double X { get; init; }
    public double Y { get; init; }

    public override string ToString() => $"({X}, {Y})";
}

結構的所有資料成員都 readonly 必須是唯讀的,如下所示:All data members of a readonly struct must be read-only as follows:

  • 任何欄位宣告都必須有 readonly 修飾Any field declaration must have the readonly modifier
  • 任何屬性(包括自動執行的屬性)都必須是唯讀的。Any property, including auto-implemented ones, must be read-only. 在 c # 9.0 和更新版本中,屬性可能具有 init 存取子。In C# 9.0 and later, a property may have an init accessor.

這可保證結構的成員不會 readonly 修改結構的狀態。That guarantees that no member of a readonly struct modifies the state of the struct. 在 c # 8.0 和更新版本中,這表示其他實例成員(除了函式之外)是隱含的 readonlyIn C# 8.0 and later, that means that other instance members except constructors are implicitly readonly.

注意

readonly 結構中,可變動參考型別的資料成員仍可以改變本身的狀態。In a readonly struct, a data member of a mutable reference type still can mutate its own state. 例如,您無法取代 List<T> 實例,但是可以在其中加入新的元素。For example, you can't replace a List<T> instance, but you can add new elements to it.

readonly 實例成員readonly instance members

從 c # 8.0 開始,您也可以使用 readonly 修飾詞來宣告實例成員不會修改結構的狀態。Beginning with C# 8.0, you can also use the readonly modifier to declare that an instance member doesn't modify the state of a struct. 如果您無法將整個結構類型宣告為 readonly ,請使用 readonly 修飾詞來標記不會修改結構狀態的實例成員。If you can't declare the whole structure type as readonly, use the readonly modifier to mark the instance members that don't modify the state of the struct.

readonly 實例成員中,您無法指派給結構的實例欄位。Within a readonly instance member, you can't assign to structure's instance fields. 不過, readonly 成員可以呼叫非 readonly 成員。However, a readonly member can call a non-readonly member. 在這種情況下,編譯器會建立結構實例的複本,並呼叫 readonly 該複本上的非成員。In that case the compiler creates a copy of the structure instance and calls the non-readonly member on that copy. 因此,原始的結構實例不會被修改。As a result, the original structure instance is not modified.

一般來說,您會將 readonly 修飾詞套用至下列類型的實例成員:Typically, you apply the readonly modifier to the following kinds of instance members:

  • 方法:methods:

    public readonly double Sum()
    {
        return X + Y;
    }
    

    您也可以將修飾詞套用 readonly 至覆寫在中宣告之方法的方法 System.ObjectYou can also apply the readonly modifier to methods that override methods declared in System.Object:

    public readonly override string ToString() => $"({X}, {Y})";
    
  • 屬性和索引子:properties and indexers:

    private int counter;
    public int Counter
    {
        readonly get => counter;
        set => counter = value;
    }
    

    如果您需要將修飾詞套用 readonly 至屬性或索引子的兩個存取子,請將它套用至屬性或索引子的宣告中。If you need to apply the readonly modifier to both accessors of a property or indexer, apply it in the declaration of the property or indexer.

    注意

    編譯器會將 get 自動執行之屬性 的存取子宣告為 readonly ,而不論屬性宣告中的修飾詞是否存在 readonlyThe compiler declares a get accessor of an auto-implemented property as readonly, regardless of presence of the readonly modifier in a property declaration.

    在 c # 9.0 和更新版本中,您可以 readonly 使用存取子將修飾詞套用至屬性或索引子 initIn C# 9.0 and later, you may apply the readonly modifier to a property or indexer with an init accessor:

    public readonly double X { get; init; }
    

您無法將修飾詞套用 readonly 至結構類型的靜態成員。You can't apply the readonly modifier to static members of a structure type.

編譯器可能會使用 readonly 修飾詞進行效能優化。The compiler may make use of the readonly modifier for performance optimizations. 如需詳細資訊,請參閱 撰寫安全且有效率的 c # 程式碼For more information, see Write safe and efficient C# code.

結構類型設計的限制Limitations with the design of a structure type

當您設計結構類型時,與 類別 類型具有相同的功能,但有下列例外狀況:When you design a structure type, you have the same capabilities as with a class type, with the following exceptions:

  • 您無法宣告無參數的函式。You can't declare a parameterless constructor. 每個結構類型都已提供隱含的無參數函式,其會產生型別的 預設值Every structure type already provides an implicit parameterless constructor that produces the default value of the type.

  • 您無法在宣告時初始化實例欄位或屬性。You can't initialize an instance field or property at its declaration. 不過,您可以在宣告時初始化 靜態const 欄位或靜態屬性。However, you can initialize a static or const field or a static property at its declaration.

  • 結構類型的函式必須初始化類型的所有實例欄位。A constructor of a structure type must initialize all instance fields of the type.

  • 結構類型無法繼承自其他類別或結構類型,而且不能是類別的基底。A structure type can't inherit from other class or structure type and it can't be the base of a class. 不過,結構類型可以執行 介面However, a structure type can implement interfaces.

  • 您無法在結構 類型中宣告 完成項。You can't declare a finalizer within a structure type.

結構類型的具現化Instantiation of a structure type

在 c # 中,您必須先初始化已宣告的變數,才能使用它。In C#, you must initialize a declared variable before it can be used. 因為結構類型變數無法 null (,除非它是 可為 null 實值型 別) 的變數,所以您必須具現化對應類型的實例。Because a structure-type variable can't be null (unless it's a variable of a nullable value type), you must instantiate an instance of the corresponding type. 有幾種方法可以這麼做。There are several ways to do that.

一般來說,您可以使用運算子呼叫適當的函式,以具現化結構類型 newTypically, you instantiate a structure type by calling an appropriate constructor with the new operator. 每個結構類型都至少有一個函數。Every structure type has at least one constructor. 這是隱含無參數的函式,它會產生型別的 預設值That's an implicit parameterless constructor, which produces the default value of the type. 您也可以使用 預設值運算式 來產生型別的預設值。You can also use a default value expression to produce the default value of a type.

如果結構類型的所有實例欄位都可以存取,您也可以在不使用運算子的情況下將它具現化 newIf all instance fields of a structure type are accessible, you can also instantiate it without the new operator. 在這種情況下,您必須在第一次使用實例之前,初始化所有的實例欄位。In that case you must initialize all instance fields before the first use of the instance. 下列範例顯示如何執行該項工作:The following example shows how to do that:

public static class StructWithoutNew
{
    public struct Coords
    {
        public double x;
        public double y;
    }

    public static void Main()
    {
        Coords p;
        p.x = 3;
        p.y = 4;
        Console.WriteLine($"({p.x}, {p.y})");  // output: (3, 4)
    }
}

在內 建實值型別的情況下,請使用對應的常值來指定類型的值。In the case of the built-in value types, use the corresponding literals to specify a value of the type.

以傳址方式傳遞結構類型變數Passing structure-type variables by reference

當您將結構類型變數當作引數傳遞至方法,或是從方法傳回結構類型值時,會複製結構類型的整個實例。When you pass a structure-type variable to a method as an argument or return a structure-type value from a method, the whole instance of a structure type is copied. 這可能會影響您的程式碼在涉及大型結構類型的高效能案例中的效能。That can affect the performance of your code in high-performance scenarios that involve large structure types. 您可以藉由傳址方式傳遞結構類型變數,以避免值複製。You can avoid value copying by passing a structure-type variable by reference. 使用 refout 或方法參數修飾詞 in 來表示引數必須以傳址方式傳遞。Use the ref, out, or in method parameter modifiers to indicate that an argument must be passed by reference. 使用 ref return 以傳址方式傳回方法結果。Use ref returns to return a method result by reference. 如需詳細資訊,請參閱 撰寫安全且有效率的 c # 程式碼For more information, see Write safe and efficient C# code.

ref 結構ref struct

從 c # 7.2 開始,您可以 ref 在結構類型的宣告中使用修飾詞。Beginning with C# 7.2, you can use the ref modifier in the declaration of a structure type. ref結構類型的實例會在堆疊上配置,而且無法對 managed 堆積進行 escape。Instances of a ref struct type are allocated on the stack and can't escape to the managed heap. 為了確保這一點,編譯器會限制結構類型的使用方式,如下所示 refTo ensure that, the compiler limits the usage of ref struct types as follows:

  • ref結構不能是陣列的元素類型。A ref struct can't be the element type of an array.
  • ref結構不能是類別或非結構之欄位的宣告型別 refA ref struct can't be a declared type of a field of a class or a non-ref struct.
  • ref結構無法執行介面。A ref struct can't implement interfaces.
  • ref結構不能封裝成 System.ValueTypeSystem.ObjectA ref struct can't be boxed to System.ValueType or System.Object.
  • ref結構不能是型別引數。A ref struct can't be a type argument.
  • ref Lambda 運算式區域函數無法捕捉結構變數。A ref struct variable can't be captured by a lambda expression or a local function.
  • ref結構變數不能用在方法中 asyncA ref struct variable can't be used in an async method. 不過,您可以 ref 在同步方法中使用結構變數,例如,在傳回或的 TaskTask<TResult>However, you can use ref struct variables in synchronous methods, for example, in those that return Task or Task<TResult>.
  • ref結構變數不能用在反覆運算器中。A ref struct variable can't be used in iterators.

一般來說, ref 當您需要也包含結構類型之資料成員的型別時,您會定義結構類型 refTypically, you define a ref struct type when you need a type that also includes data members of ref struct types:

public ref struct CustomRef
{
    public bool IsValid;
    public Span<int> Inputs;
    public Span<int> Outputs;
}

若要將 ref 結構宣告為 readonly ,請 readonly 在類型宣告中結合和修飾詞, ref (修飾詞必須在修飾詞 readonly ref) 之前:To declare a ref struct as readonly, combine the readonly and ref modifiers in the type declaration (the readonly modifier must come before the ref modifier):

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 包括 System.Span<T>System.ReadOnlySpan<T>In .NET, examples of a ref struct are System.Span<T> and System.ReadOnlySpan<T>.

轉換Conversions

若為任何結構類型 ( ref 結構類型除外) ,則會在和類型之間存在的裝箱和取消加入轉換 System.ValueType System.ObjectFor any structure type (except ref struct types), there exist boxing and unboxing conversions to and from the System.ValueType and System.Object types. 結構類型和它所執行的任何介面之間,也有另外的裝箱和取消程式轉換。There exist also boxing and unboxing conversions between a structure type and any interface that it implements.

C# 語言規格C# language specification

如需詳細資訊,請參閱c # 語言規格結構一節。For more information, see the Structs section of the C# language specification.

如需有關 c # 7.2 和更新版本中所引進之功能的詳細資訊,請參閱下列功能提案附注:For more information about features introduced in C# 7.2 and later, see the following feature proposal notes:

請參閱See also