.NET ヘルプ

C# 構造体 vs クラス (開発者のための仕組み)

C#において、構造体(struct)とクラス(class)はいずれもデータを整理および格納するための基本的な構成要素ですが、異なるシナリオに適した特有の特徴を持っています。 C# の構造体とクラス の違いを理解することは、C# アプリケーションを設計する際に情報に基づいた意思決定を行うために重要です。

この記事では、構造体とクラスの主要な違いを探り、その使用例、メモリ管理、およびパフォーマンスへの影響について論じます。 また、PDFファイルの作成においてIronPDF for C#とともに構造体とクラスの使用方法についても説明します。

構造体とクラスの概要

1.1. クラス(参照型)

参照型: C#のクラスはヒープ上に存在する参照型です。つまり、クラスのインスタンスが作成されると、そのオブジェクトへの参照がメモリに保存されます。

ヒープ割り当て: クラスインスタンスはヒープメモリの割り当てでメモリが割り当てられ、サイズの柔軟性を提供し、オブジェクトがコードの異なる部分間で共有されることを可能にします。

デフォルトコンストラクタ: クラスはデフォルトコンストラクタを持つことができ、これは明示的に定義されていない場合に自動的に提供されます。

継承: クラスは継承をサポートしており、共有の特徴を持つ派生クラスの作成を可能にします。

using System;
// Define a class
public class MyClass
{
    // Fields (data members)
    public int MyField;
    // Constructor
    public MyClass(int value)
    {
        MyField = value;
    }
    // Method
    public void Display()
    {
        Console.WriteLine($"Value in MyClass: {MyField}");
    }
}
class Program
{
    static void Main()
    {
        // Create an instance of the class
        MyClass myClassInstance = new MyClass(10);
        // Access field and call method
        myClassInstance.Display();
        // Classes are reference types, so myClassInstance refers to the same object in memory
        MyClass anotherInstance = myClassInstance;
        anotherInstance.MyField = 20;
        // Both instances refer to the same object, so the change is reflected in both
        myClassInstance.Display();
        anotherInstance.Display();
    }
}
using System;
// Define a class
public class MyClass
{
    // Fields (data members)
    public int MyField;
    // Constructor
    public MyClass(int value)
    {
        MyField = value;
    }
    // Method
    public void Display()
    {
        Console.WriteLine($"Value in MyClass: {MyField}");
    }
}
class Program
{
    static void Main()
    {
        // Create an instance of the class
        MyClass myClassInstance = new MyClass(10);
        // Access field and call method
        myClassInstance.Display();
        // Classes are reference types, so myClassInstance refers to the same object in memory
        MyClass anotherInstance = myClassInstance;
        anotherInstance.MyField = 20;
        // Both instances refer to the same object, so the change is reflected in both
        myClassInstance.Display();
        anotherInstance.Display();
    }
}
Imports System
' Define a class
Public Class [MyClass]
	' Fields (data members)
	Public MyField As Integer
	' Constructor
	Public Sub New(ByVal value As Integer)
		MyField = value
	End Sub
	' Method
	Public Sub Display()
		Console.WriteLine($"Value in MyClass: {MyField}")
	End Sub
End Class
Friend Class Program
	Shared Sub Main()
		' Create an instance of the class
		Dim myClassInstance As [MyClass] = New [MyClass](10)
		' Access field and call method
		myClassInstance.Display()
		' Classes are reference types, so myClassInstance refers to the same object in memory
		Dim anotherInstance As [MyClass] = myClassInstance
		anotherInstance.MyField = 20
		' Both instances refer to the same object, so the change is reflected in both
		myClassInstance.Display()
		anotherInstance.Display()
	End Sub
End Class
$vbLabelText   $csharpLabel

C# 構造体 vs クラス (開発者向けの動作方法): 図 1 - 前のコードからのコンソールの出力

1.2. 構造体 (値型)

値型: 構造体は値型であり、変数が宣言された場所に実際のデータが保存されます。これはプリミティブ型とは異なり、メモリの別の場所に保存されるわけではありません。また、構造体はNullable<>タグを使用してヌラブル型にしない限り、値型としてnull値を割り当てることはできません。

スタックアロケーション: 構造体インスタンスはスタック上にメモリが割り当てられ、それによりより高速な割り当てと解放が可能ですが、サイズとスコープに制限があります。

デフォルトコンストラクタなし: 構造体は、明示的に定義されない限り、デフォルトコンストラクタを持ちません。 インスタンス化の際にすべてのフィールドを初期化する必要があります。

継承なし: 構造体は継承をサポートしません。 それらは主に軽量なデータ構造のために使用されます。

using System;
// Define a struct
public struct MyStruct
{
    // Fields (data members)
    public int MyField;
    // Constructor
    public MyStruct(int value)
    {
        MyField = value;
    }
    // Method
    public void Display()
    {
        Console.WriteLine($"Value in MyStruct: {MyField}");
    }
}
class Program
{
    static void Main()
    {
        // Create an instance of the struct
        MyStruct myStructInstance = new MyStruct(10);
        // Access field and call method
        myStructInstance.Display();
        // Structs are value types, so myStructInstance is a copy
        MyStruct anotherInstance = myStructInstance;
        anotherInstance.MyField = 20;
        // Changes to anotherInstance do not affect myStructInstance
        myStructInstance.Display();
        anotherInstance.Display();
    }
}
using System;
// Define a struct
public struct MyStruct
{
    // Fields (data members)
    public int MyField;
    // Constructor
    public MyStruct(int value)
    {
        MyField = value;
    }
    // Method
    public void Display()
    {
        Console.WriteLine($"Value in MyStruct: {MyField}");
    }
}
class Program
{
    static void Main()
    {
        // Create an instance of the struct
        MyStruct myStructInstance = new MyStruct(10);
        // Access field and call method
        myStructInstance.Display();
        // Structs are value types, so myStructInstance is a copy
        MyStruct anotherInstance = myStructInstance;
        anotherInstance.MyField = 20;
        // Changes to anotherInstance do not affect myStructInstance
        myStructInstance.Display();
        anotherInstance.Display();
    }
}
Imports System
' Define a struct
Public Structure MyStruct
	' Fields (data members)
	Public MyField As Integer
	' Constructor
	Public Sub New(ByVal value As Integer)
		MyField = value
	End Sub
	' Method
	Public Sub Display()
		Console.WriteLine($"Value in MyStruct: {MyField}")
	End Sub
End Structure
Friend Class Program
	Shared Sub Main()
		' Create an instance of the struct
		Dim myStructInstance As New MyStruct(10)
		' Access field and call method
		myStructInstance.Display()
		' Structs are value types, so myStructInstance is a copy
		Dim anotherInstance As MyStruct = myStructInstance
		anotherInstance.MyField = 20
		' Changes to anotherInstance do not affect myStructInstance
		myStructInstance.Display()
		anotherInstance.Display()
	End Sub
End Class
$vbLabelText   $csharpLabel

C# 構造体 vs クラス(開発者向けの動作方法):図 2 - 前のコードのコンソール出力

利用事例とガイドライン

2.1. クラスの使用タイミング

複雑な状態と振る舞い: 状態と振る舞いを伴った複雑なデータ構造をモデル化する必要がある場合は、クラスを使用します。 クラスは、複数のプロパティおよびメソッドを持つ複雑なオブジェクトを表現するのに適しています。

参照セマンティクス: オブジェクトのインスタンスを共有し、コードの異なる部分に変更が反映されるようにしたい場合、クラスが適切な選択です。

2.2. 構造体を使用するタイミング

シンプルなデータ構造: 構造体は、小さなデータ構造(ポイント、長方形、キーと値のペアなど)や論理的に単一の値を表す場合に適した軽量なエンティティを表現するのに理想的です。

値セマンティクス: 値セマンティクスを好み、ヒープ割り当てのオーバーヘッドを避けたい場合、構造体が適しています。

パフォーマンス上の考慮事項: パフォーマンスが重要であるシナリオ、特に小さく頻繁に使用されるオブジェクトにおいては、スタック配置により構造体がより効率的な場合があります。

メモリ割り当ての違い

3.1. クラス

参照カウント: クラスインスタンスのメモリは、ガーベッジコレクタによる参照カウントで管理されます。 オブジェクトは、それに対する参照がなくなったときにガベージコレクションの対象となります。

メモリリークの可能性: 参照の不適切な取り扱いによって、不要になったオブジェクトが適切に破棄されない場合、メモリリークが発生する可能性があります。

3.2. 構造体

ガベージコレクションなし: 構造体(Struct)は値型であるため、ガベージコレクションに依存せず、異なる方法で管理されます。 スコープから外れたときに自動的に解放されます。

限定されたメモリオーバーヘッド: 構造体はクラスに比べてメモリオーバーヘッドが低いため、メモリ使用量が問題となるシナリオでは効率的です。

パフォーマンスの考慮事項

クラス

間接アクセス: クラスインスタンスは参照を通じてアクセスされるため、間接参照のレベルが追加され、わずかなパフォーマンスのオーバーヘッドが生じる可能性があります。

ヒープ割り当て: ヒープ上でのメモリの動的割り当ては、オブジェクトの作成および破棄時間の延長につながる可能性があります。

構造体

直接アクセス: 構造体は直接アクセスされ、追加の間接参照が不要です。 これは、小さく頻繁に使用されるオブジェクトのパフォーマンスを向上させる可能性があります。

スタック割り当て: スタックのメモリ割り当ては、構造体インスタンスの迅速な作成と破棄を可能にします。

5. IronPDFの紹介

IronPDF 概要: PDF 操作のための強力な C# ライブラリ は、.NET アプリケーション内で円滑な PDF の生成、操作、およびレンダリングを目的としています。 IronPDFを使用すると、開発者はPDFドキュメントを簡単に作成、修正、および操作できるため、HTMLコンテンツから動的にPDFを生成することから、既存のドキュメントからデータを抽出することに至るまで、様々なタスクにおいて不可欠なツールとなります。 この多用途ライブラリはPDF関連機能を簡素化し、Webアプリケーション、デスクトップソフトウェア、または効率的なPDF処理を必要とするあらゆる.NETプロジェクトに取り組む開発者向けの包括的な機能セットを提供します。

IronPDFのインストール

コード例に進む前に、IronPDFをインストールする必要があります。 この操作は、NuGetパッケージマネージャーコンソールを使用するか、プロジェクトにIronPDFライブラリを追加することで行うことができます。 次の手順は、インストールプロセスを説明しています:

  1. NuGet パッケージ マネージャー コンソール:
    :ProductInstall
    :ProductInstall
SHELL
  1. パッケージマネージャーUI: NuGetパッケージマネージャーUIで「IronPDF」を検索し、最新バージョンをインストールします。

    IronPDFをインストールすると、C#アプリケーションでPDFファイル処理にその機能を活用する準備が整います。

5.2. IronPDFでStructとClassを使用する

using IronPdf;
using System;
// Sample class
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
// Sample struct
struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}
class Program
{
    static void Main()
    {
        // Sample instances of class and struct
        Person person = new Person { Name = "John Doe", Age = 30 };
        Point point = new Point { X = 10, Y = 20 };
        // Create a new PDF document
        var renderer = new ChromePdfRenderer();
        // Add content with information from class and struct
        string content = $@"<!DOCTYPE html>
                            <html>
                            <body>
                                <h1>Information in IronPDF</h1>
                                <p>Name: {person.Name}</p>
                                <p>Age: {person.Age}</p>
                                <p>Point X: {point.X}</p>
                                <p>Point Y: {point.Y}</p>
                            </body>
                            </html>";
        // Render HTML content to PDF
        var pdf = renderer.RenderHtmlAsPdf(content);
        // Save the PDF to a file
        pdf.SaveAs("InformationDocument.pdf");
    }
}
using IronPdf;
using System;
// Sample class
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
// Sample struct
struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}
class Program
{
    static void Main()
    {
        // Sample instances of class and struct
        Person person = new Person { Name = "John Doe", Age = 30 };
        Point point = new Point { X = 10, Y = 20 };
        // Create a new PDF document
        var renderer = new ChromePdfRenderer();
        // Add content with information from class and struct
        string content = $@"<!DOCTYPE html>
                            <html>
                            <body>
                                <h1>Information in IronPDF</h1>
                                <p>Name: {person.Name}</p>
                                <p>Age: {person.Age}</p>
                                <p>Point X: {point.X}</p>
                                <p>Point Y: {point.Y}</p>
                            </body>
                            </html>";
        // Render HTML content to PDF
        var pdf = renderer.RenderHtmlAsPdf(content);
        // Save the PDF to a file
        pdf.SaveAs("InformationDocument.pdf");
    }
}
Imports IronPdf
Imports System
' Sample class
Friend Class Person
	Public Property Name() As String
	Public Property Age() As Integer
End Class
' Sample struct
Friend Structure Point
	Public Property X() As Integer
	Public Property Y() As Integer
End Structure
Friend Class Program
	Shared Sub Main()
		' Sample instances of class and struct
		Dim person As New Person With {
			.Name = "John Doe",
			.Age = 30
		}
		Dim point As New Point With {
			.X = 10,
			.Y = 20
		}
		' Create a new PDF document
		Dim renderer = New ChromePdfRenderer()
		' Add content with information from class and struct
		Dim content As String = $"<!DOCTYPE html>
                            <html>
                            <body>
                                <h1>Information in IronPDF</h1>
                                <p>Name: {person.Name}</p>
                                <p>Age: {person.Age}</p>
                                <p>Point X: {point.X}</p>
                                <p>Point Y: {point.Y}</p>
                            </body>
                            </html>"
		' Render HTML content to PDF
		Dim pdf = renderer.RenderHtmlAsPdf(content)
		' Save the PDF to a file
		pdf.SaveAs("InformationDocument.pdf")
	End Sub
End Class
$vbLabelText   $csharpLabel
  • Person は、NameAge プロパティを持つ人を表すサンプルクラスです。
  • Pointは、XプロパティとYプロパティを持つ2D座標系の点を表すサンプルの構造体です。
  • Person クラスとPoint 構造体のインスタンスが作成されます。
  • HTMLコンテンツはPDFドキュメントにレンダリングされ、「InformationDocument.pdf」として保存されます。

出力PDFファイル

C# 構造体 vs クラス(開発者向けの仕組み):図 3 - 前のコードから出力された PDF ファイル

結論

結論として、C#の構造体とクラスを使用する選択は、アプリケーションの具体的な要件と特性によります。 クラスは、参照型であるため、状態と動作を持つ複雑なエンティティのモデリングに適しており、継承をサポートし、共有インスタンスを容易にします。 一方、値型としての構造体は、値セマンティクスを持つ軽量なデータ構造に最適であり、スタック割り当てや直接アクセスにおける性能上の利点を提供します。

IronPDFはユーザーに評価用の無料トライアルライセンスを提供しており、IronPDFの機能や特長を知る良い機会となります。 IronPDFについて詳しく知りたい方は、包括的なIronPDFドキュメントをご覧ください。そして、IronPDFを使用してPDFファイルを作成するための詳細なチュートリアルは、IronPDF PDF生成チュートリアルで利用可能です。

チペゴ
ソフトウェアエンジニア
チペゴは優れた傾聴能力を持ち、それが顧客の問題を理解し、賢明な解決策を提供する助けとなっています。彼は情報技術の学士号を取得後、2023年にIron Softwareチームに加わりました。現在、彼はIronPDFとIronOCRの2つの製品に注力していますが、顧客をサポートする新しい方法を見つけるにつれて、他の製品に関する知識も日々成長しています。Iron Softwareでの協力的な生活を楽しんでおり、さまざまな経験を持つチームメンバーが集まり、効果的で革新的な解決策を提供することに貢献しています。チペゴがデスクを離れているときは、良い本を楽しんだり、サッカーをしていることが多いです。
< 以前
C#で配列を初期化する方法(開発者向け)
次へ >
NPlot C#(開発者向けの使用方法)