なんかいろいろと書いてくブログ

関東のどこかで働く、一般人

【C#】構造体(Struct)について①

プロダクトコードを触っていると、struct がたまに出てくるが class との違いがよくわかっていなかったのでメモ

公式ドキュメント

公式は正義
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/builtin-types/struct

構造体について

公式によると、

"構造体型" (または "構造体型") とは、データおよび関連する機能をカプセル化できる 値の型です。 構造体型を定義するには、struct キーワードを使用します。

と記載されており、値の型として実装される。
この部分が class との違いになりそう

定義するには、struct キーワードを使用する

public struct HogeStruct
{
    public string x { get; set; }

    public int y { get; set; }

    public HogeStruct(string x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

public static void Main(string[] args)
{
    // コンストラクタで値を定義
    var hogeStruct = new HogeStruct("test", 3);
    // オブジェクト初期化しで値を定義
    var hogeStruct = new HogeStruct { x = "test", y = 1 };
}

実装にはコンストラクタ、オブジェクト初期化子両方で実装できる
このあたりは、クラスと扱いは同じそう

もちろんreadonlyをつけて読み取り専用にもできる

public readonly struct HogeReadOnlyStruct
{
    public string x { get; set; }

    public int y { get; set; }

    public HogeStruct(string x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

WITH

C# 10.0 からは値をコピーして変更するwithというものもあるらしい

var hogeStruct = new HogeStruct { x = "test", y = 1 };
var hogeStruct2 = hogeStruct with { x = "useWith" };
// hogeStruct2.x = "useWith"
// hogeStruct2.y = 1

インスタンス化

https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/builtin-types/struct#instantiation-of-a-structure-type
通常、構造体は使用する前にnew演算子を使用して初期化する必要があるが、
(ここは class と同じ)

構造体のフィールド全てにアクセスできる場合は
new演算子なしでインタンス化できる

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

    public static void Main()
    {
        Coords p;
        p.x = 3;
        p.y = 4;
    }
}

制限事項

基本的には class と同じように使えるらしいが、
class に対していくつかの制限事項がある その中の一つがパラメータなしのコンストラクタを実装できないとこにある https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/builtin-types/struct#limitations-with-the-design-of-a-structure-type

理由としては
構造体では、すでにパラメータありのコンストラクタがすでに実装されているようで、
後から引数なしでは実装できないとのこと
(C# 10.0 からは可能らしい)

withoutargs
引数をしていないと怒られる

Structはclassと同じように扱えるようで、 異なる部分が多い そのためか、class と比較した記事ををよく見かける classと使い分けるにはその辺も整理しなければならなそうなので
その部分は別途、記事としてまとめようと思う