構造体

# 構造体の宣言

public struct Vector 
{
    public int X;
    public int Y;
    public int Z;
}

public struct Point
{
    public decimal x, y;
    
    public Point(decimal pointX, decimal pointY)
    {
        x = pointX;
        y = pointY;
    }
}

  • `struct` インスタンス フィールドは、パラメータ化されたコンストラクタを介して、または `struct` 構築後に個別に設定できます。
  • プライベート メンバーは、コンストラクターによってのみ初期化できます。
  • `struct` は、System.ValueType から暗黙的に継承するシール型を定義します。
  • 構造体は他の型から継承できませんが、インターフェースを実装できます。
  • 構造体は代入時にコピーされます。つまり、すべてのデータが新しいインスタンスにコピーされ、一方への変更は他方には反映されません。
  • 構造体は「null」にはできませんが、null 許容型として使用することは**できます**:
    Vector v1 = null; //illegal
    Vector? v2 = null; //OK
    Nullable<Vector> v3 = null // OK
    
    
  • 構造体は、`new` 演算子を使用して、または使用せずにインスタンス化できます。
    //Both of these are acceptable
    Vector v1 = new Vector();
    v1.X = 1;
    v1.Y = 2;
    v1.Z = 3;
    
    Vector v2;
    v2.X = 1;
    v2.Y = 2;
    v2.Z = 3;
    
    

    ただし、new イニシャライザを使用するには、演算子を使用する必要があります:

    Vector v1 = new MyStruct { X=1, Y=2, Z=3 }; // OK
    Vector v2 { X=1, Y=2, Z=3 }; // illegal
    
    
  • 構造体は、いくつかの例外を除いて、クラスが宣言できるすべてのものを宣言できます:

    • 構造体は、パラメーターなしのコンストラクターを宣言できません。 struct インスタンスフィールドは、パラメーター化されたコンストラクターを介して、または struct の後に個別に設定できます 工事。プライベート メンバーは、コンストラクターによってのみ初期化できます。
    • 暗黙的にシールされているため、構造体はメンバーを保護されていると宣言できません。
    • 構造体フィールドは、const または static の場合にのみ初期化できます。

    # 構造体の使用法

    コンストラクタの場合:

    Vector v1 = new Vector();
    v1.X = 1;
    v1.Y = 2;
    v1.Z = 3;
    
    Console.WriteLine("X = {0}, Y = {1}, Z = {2}",v1.X,v1.Y,v1.Z);
    // Output X=1,Y=2,Z=3
    
    Vector v1 = new Vector();
    //v1.X is not assigned
    v1.Y = 2;
    v1.Z = 3;
    
    Console.WriteLine("X = {0}, Y = {1}, Z = {2}",v1.X,v1.Y,v1.Z);
    // Output X=0,Y=2,Z=3
    
    Point point1 = new Point();
    point1.x = 0.5;
    point1.y = 0.6;
    
    Point point2 = new Point(0.5, 0.6);
    
    

    コンストラクタなし:

    Vector v1;
    v1.Y = 2;
    v1.Z = 3;
    
    Console.WriteLine("X = {0}, Y = {1}, Z = {2}",v1.X,v1.Y,v1.Z);
    //Output ERROR "Use of possibly unassigned field 'X'
    
    Vector v1;
    v1.X = 1;
    v1.Y = 2;
    v1.Z = 3;
    
    Console.WriteLine("X = {0}, Y = {1}, Z = {2}",v1.X,v1.Y,v1.Z);
    // Output X=1,Y=2,Z=3
    
    Point point3;
    point3.x = 0.5;
    point3.y = 0.6;
    
    

    コンストラクターで構造体を使用すると、割り当てられていないフィールドで問題が発生することはありません (割り当てられていない各フィールドには null 値があります)。

    クラスとは異なり、構造体を構築する必要はありません。つまり、コンストラクターの 1 つを呼び出す必要がない限り、 new キーワードを使用する必要はありません。構造体は値型であり、null にすることはできないため、new キーワードは必要ありません。

    # 構造体実装インターフェース

    public interface IShape
    {
        decimal Area();
    }
    
    public struct Rectangle : IShape
    {
        public decimal Length { get; set; }
        public decimal Width { get; set; }
    
        public decimal Area()
        {
            return Length * Width;
        }
    }
    
    

    # 割り当て時に構造体がコピーされます

    構造体は値型であるため、すべてのデータがコピーされます 新しいコピーを変更しても、元のコピーのデータは変更されません。以下のコード スニペットは、p1 を示しています。 コピー p2p1 で行われた変更 p2 には影響しません インスタンス。

    var p1 = new Point {
        x = 1,
        y = 2
    };
    
    Console.WriteLine($"{p1.x} {p1.y}"); // 1 2
    
    var p2 = p1;
    Console.WriteLine($"{p2.x} {p2.y}"); // Same output: 1 2
    
    p1.x = 3;
    Console.WriteLine($"{p1.x} {p1.y}"); // 3 2
    Console.WriteLine($"{p2.x} {p2.y}"); // p2 remain the same: 1 2
    
    

    # コメント

    クラスとは異なり、struct 値型であり、デフォルトではマネージド ヒープではなくローカル スタックに作成されます .これは、特定のスタックが範囲外になると、struct 割り当てが解除されます。割り当て解除された struct の含まれる参照型 struct によって参照されなくなったと GC が判断すると、s もスイープされます。 .

    struct s は継承できず、継承のベースにすることもできません。それらは暗黙的に封印されており、protected を含めることもできません。 メンバー。ただし、struct クラスと同様にインターフェースを実装できます。