C# 结构体(Struct)

C# において、構造体(struct)は値型(value type)であり、関連するデータを整理して格納するために使用されます。

C# において、構造体は値型のデータ構造であり、これにより単一の変数でさまざまなデータ型の関連データを格納できます。

structキーワードは構造体を作成するために使用されます。

構造体はレコードを表すために使われます。図書館の本の動きを追跡したいと仮定すると、各本について以下の属性を追跡したいかもしれません。

  • Title
  • Author
  • Subject
  • Book ID

定义结构体

構造体を定義するには、次を使用する必要があります。struct语句。

structステートメントは、プログラムに複数のメンバーを持つ新しいデータ型を定義します。

たとえば、次のようにBook構造体を宣言できます。

struct Books
{
   public string title;
   public string author;
   public string subject;
   public int book_id;
};  

以下のプログラムは構造体の使用方法を示しています:

实例

using System;
using System.Text;
     
struct Books
{
   public string title;
   public string author;
   public string subject;
   public int book_id;
};  

public class testStructure
{
   public static void Main(string[] args)
   {

      Books Book1;        /* Book1 を宣言、型は Books */
      Books Book2;        /* Book2 を宣言、型は Books */

      /* book 1 详述 */
      Book1.title = "C Programming";
      Book1.author = "Nuha Ali";
      Book1.subject = "C Programming Tutorial";
      Book1.book_id = 6495407;

      /* book 2 详述 */
      Book2.title = "Telecom Billing";
      Book2.author = "Zara Ali";
      Book2.subject =  "Telecom Billing Tutorial";
      Book2.book_id = 6495700;

      /* 打印 Book1 信息 */
      Console.WriteLine( "Book 1 title : {0}", Book1.title);
      Console.WriteLine("Book 1 author : {0}", Book1.author);
      Console.WriteLine("Book 1 subject : {0}", Book1.subject);
      Console.WriteLine("Book 1 book_id :{0}", Book1.book_id);

      /* 打印 Book2 信息 */
      Console.WriteLine("Book 2 title : {0}", Book2.title);
      Console.WriteLine("Book 2 author : {0}", Book2.author);
      Console.WriteLine("Book 2 subject : {0}", Book2.subject);
      Console.WriteLine("Book 2 book_id : {0}", Book2.book_id);      

      Console.ReadKey();

   }
}

上記のコードがコンパイルおよび実行されると、次の結果が生成されます:

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

C# 構造体の特徴

構造体は、単純なデータ構造を表すのに適した軽量なデータ型を提供し、優れたパフォーマンス特性と値セマンティクスを備えています。

  • 構造体は、メソッド、フィールド、インデックス、プロパティ、演算子メソッド、イベントを持つことができ、座標、範囲、日付、時刻などの軽量データを表す場合に適しています。
  • 構造体はコンストラクターを定義できますが、デストラクターは定義できません。ただし、構造体にパラメーターなしのコンストラクターを定義することはできません。パラメーターなしのコンストラクター(デフォルト)は自動的に定義され、変更できません。
  • クラスとは異なり、構造体は他の構造体やクラスを継承できません。
  • 構造体は、他の構造体やクラスの基本構造体にはなれません。
  • 構造体は1つ以上のインターフェースを実装できます。
  • 構造体メンバーは abstract、virtual、protected として指定できません。
  • 当您使用New演算子を使用して構造オブジェクトを作成すると、適切なコンストラクターが呼び出されて構造が作成されます。クラスとは異なり、構造体は new 演算子を使用せずにインスタンス化できます。
  • New演算子を使用しない場合、すべてのフィールドが初期化された後にのみ、フィールドへの代入が行われ、オブジェクトが使用されます。
  • 構造体変数は通常スタック上に割り当てられるため、作成と破棄が高速です。ただし、構造体をクラスのフィールドとして使用し、そのクラスが参照型である場合、構造体はヒープ上に格納されます。
  • 構造体はデフォルトで可変です。つまり、そのフィールドを変更できます。ただし、構造体が読み取り専用として定義されている場合、そのフィールドは不変になります。

クラス vs 構造体

クラスと構造体には、設計および使用時において異なる考慮事項があります。クラスは複雑なオブジェクトや動作を表すのに適しており、継承やポリモーフィズムをサポートします。一方、構造体は軽量データや値型を表すのに適しており、パフォーマンスを向上させ、参照の管理オーバーヘッドを回避します。

クラスと構造体には、以下の基本的な相違点があります。

値型 vs 参照型:

  • 構造体は値型(Value Type)です:構造体は値型であり、スタック上にメモリが割り当てられ、ヒープ上には割り当てられません。構造体インスタンスをメソッドに渡すか別の変数に代入すると、構造体全体の内容がコピーされます。
  • クラスは参照型(Reference Type)です:クラスは参照型であり、ヒープ上にメモリが割り当てられます。クラスインスタンスをメソッドに渡すか別の変数に代入する場合、実際にはオブジェクト全体のコピーではなく参照(メモリアドレス)が渡されます。

継承と多態性:

  • 構造体は継承できません:構造体は他の構造体やクラスを継承できず、他の構造体やクラスの基本クラスにもなれません。
  • クラスは継承をサポートします:クラスは継承とポリモーフィズムをサポートし、新しいクラスを派生させることで既存のクラスの機能を拡張できます。

デフォルトコンストラクタ:

  • 構造体は引数なしのコンストラクターを持つことはできません:構造体はパラメーターなしのコンストラクターを含むことができません。
  • クラスは引数なしのコンストラクターを持つことができます:クラスはパラメーターなしのコンストラクターを含むことができ、コンストラクターが提供されない場合、システムがデフォルトのパラメーターなしコンストラクターを提供します。

代入の動作:

  • クラス型の変数は、代入時に参照を格納するため、2つの変数が同じオブジェクトを指します。
  • 構造体変数は代入時に構造体全体をコピーするため、各変数はそれぞれ独立したコピーを持ちます。

传递方式:

  • クラス型のオブジェクトは、メソッド呼び出し時に参照渡しされます。つまり、メソッド内でオブジェクトに加えられた変更は、元のオブジェクトに影響します。
  • 構造体オブジェクトは通常、値渡しされます。つまり、渡されるのは構造体のコピーであり、元の構造体オブジェクト自体ではありません。したがって、メソッド内で構造体に加えられた変更は、元のオブジェクトに影響しません。

可空性:

  • 構造体は値型であり、直接~に設定することはできません。null:なぜならnullは参照型のデフォルト値であり、値型のデフォルト値ではありません。構造体変数の欠落または無効な状態を表す必要がある場合は、~を使用できます。Nullable<T>または呼ばれるT?のnull許容型。
  • クラスはデフォルトでnullにできます:クラスのインスタンスはデフォルトでnullにできますnull,それらは参照型であるためです。

パフォーマンスとメモリ割り当て:

  • 構造体は通常より軽量です:構造体は値型でありスタック上にメモリが割り当てられるため、通常はクラスよりも軽量で、単純なデータ表現に適しています。
  • クラスにはより多くのオーバーヘッドがかかる可能性があります:クラスは参照型であるため、より多くのメモリオーバーヘッドと管理が必要になる場合があります。

以下の例では、MyStruct は構造体で、MyClass はクラスです。

コメント部分では、構造体が引数なしのコンストラクターを含むことができず、継承できず、構造体のインスタンスコピーが構造体全体の内容をコピーすることを示しています。これに対して、クラスは引数なしのコンストラクターを含むことができ、継承でき、インスタンスコピーは参照をコピーします。

实例

using System;

// 结构声明
struct MyStruct
{
    public int X;
    public int Y;

    // 構造体はパラメーターなしのコンストラクターを持つことはできません
    // public MyStruct()
    // {
    // }

    // パラメータ付きコンストラクタ
    public MyStruct(int x, int y)
    {
        X = x;
        Y = y;
    }

    // 结构不能继承
    // struct MyDerivedStruct : MyBaseStruct
    // {
    // }
}

// 类声明
class MyClass
{
    public int X;
    public int Y;

    // クラスは引数なしのコンストラクタを持つことができる
    public MyClass()
    {
    }

    // パラメータ付きコンストラクタ
    public MyClass(int x, int y)
    {
        X = x;
        Y = y;
    }

    // 类支持继承
    // class MyDerivedClass : MyBaseClass
    // {
    // }
}

class Program
{
    static void Main()
    {
        // 構造体は値型であり、スタック上に割り当てられる
        MyStruct structInstance1 = new MyStruct(1, 2);
        MyStruct structInstance2 = structInstance1; // 复制整个结构

        // クラスは参照型であり、ヒープ上に割り当てられる
        MyClass classInstance1 = new MyClass(3, 4);
        MyClass classInstance2 = classInstance1; // 参照をコピーし、同じオブジェクトを指す

        // 修改结构实例不影响其他实例
        structInstance1.X = 5;
        Console.WriteLine($"Struct: {structInstance1.X}, {structInstance2.X}");

        // 修改类实例会影响其他实例
        classInstance1.X = 6;
        Console.WriteLine($"Class: {classInstance1.X}, {classInstance2.X}");
    }
}

上記の議論に基づいて、前の例を書き直してみましょう:

实例

using System;
using System.Text;
     
struct Books
{
   private string title;
   private string author;
   private string subject;
   private int book_id;
   public void setValues(string t, string a, string s, int id)
   {
      title = t;
      author = a;
      subject = s;
      book_id =id;
   }
   public void display()
   {
      Console.WriteLine("Title : {0}", title);
      Console.WriteLine("Author : {0}", author);
      Console.WriteLine("Subject : {0}", subject);
      Console.WriteLine("Book_id :{0}", book_id);
   }

};  

public class testStructure
{
   public static void Main(string[] args)
   {

      Books Book1 = new Books(); /* Book1 を宣言、型は Books */
      Books Book2 = new Books(); /* Book2 を宣言、型は Books */

      /* book 1 详述 */
      Book1.setValues("C Programming",
      "Nuha Ali", "C Programming Tutorial",6495407);

      /* book 2 详述 */
      Book2.setValues("Telecom Billing",
      "Zara Ali", "Telecom Billing Tutorial", 6495700);

      /* 打印 Book1 信息 */
      Book1.display();

      /* 打印 Book2 信息 */
      Book2.display();

      Console.ReadKey();

   }
}

上記のコードがコンパイルおよび実行されると、次の結果が生成されます:

Title : C Programming
Author : Nuha Ali
Subject : C Programming Tutorial
Book_id : 6495407
Title : Telecom Billing
Author : Zara Ali
Subject : Telecom Billing Tutorial
Book_id : 6495700
其他扩展