構造体の初期化 クラスとはちょっと違う

基本用法
クラス(参照型)とは違い、構造体(値型)の初期化はちょっとクセがあります。

デフォルトコンストラクタ(引数なしのコンストラクタ)を定義できない
 (ゼロ初期化というデフォルト値で初期化するコンストラクタがコンパイラにより自動生成されるため)
コンストラクタでは全てのインスタンスフィールド(とプロパティ)を初期化する必要がある

    public struct Member
    {
        public int ID { get; set; }
        public string Name { get; set; }

        // 引数無しのデフォルトコンストラクタは定義できない
        //public Member() { }

        // 全メンバーを初期化する引数ありのコンストラクタは定義可能
        public Member(int id, string name)
        {
            ID = id;
            Name = name;
        }

        // 初期化されないメンバーがあるとダメ
        //public Member(int id)
        //{
        //    ID = id;
        //}

        // これはOK。引数ありで全メンバを初期化してる
        public Member(int id)
        {
            ID = id;
            Name = string.Empty;
        }
    }

フィールド初期化子

インスタンスフィールドまたはプロパティを宣言で初期化できない

    // クラスはOK
    public class Shop
    {
        public int ID { get; set; } = 0;
        public string Name { get; set; } = string.Empty;

        public int Score = 0;
        public string Address = string.Empty;
    }

    // 構造体はコンパイルが通らない
    //public struct Shop
    //{
    //    public int ID { get; set; } = 0;
    //    public string Name { get; set; } = string.Empty;

    //    public int Score = 0;
    //    public string Address = string.Empty;
    //}

new演算子なしでの使用

全フィールドが初期化された後でないと使えないという制約がある
    // 自動プロパティをメンバとする構造体
    public struct Member
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }

    // フィールドを直接公開している構造体
    public struct Student
    {
        public int ID;
        public string Name;
    }

    class Program
    {
        static void Main(string[] args)
        {
            // メンバがフィールド定義の場合
            Student student;

            // 全フィールド未初期化時は使えない
            //string s = student.ToString();

            student.ID = 2;
            student.Name = "ST 2";

            // フィールド初期化後は使える
            string s = student.ToString();



            // メンバーがプロパティ定義の場合

            // new 演算子だと全フィールドが初期化されるのでOK
            Member member1 = new Member();
            string s1 = member1.ToString();

            // new演算子無しだと 未割当のローカル変数があるのでプロパティを触れない
            //Member member2;
            //member2.ID = 2;
            //member2.Name = "MEM 2";
            //string s2 = member2.ToString();

            // オブジェクト初期化子で初期化するのはOK
            Member member3 = new Member
            {
                ID = 3,
                Name = "MEM 3"
            };

            string s3 = member3.ToString();
        }
    }

補足

※C#6.0のリリース版から文法がちょっと変わったようです。
    public struct Shop
    {
        public int ID { get; set; } 
        public string Name { get; set; }

        // プロパティにアクセスする前にデフォルトコンストラクタを読んで
        // バッキングストアのフィールドを初期化しておく必要があった
        public Shop(int id, string name): this()
        {
            ID = id;
            Name = name;
        } 


        // ※今はこれが可能に変更(直接バッキングストア側を初期化する)
        public Shop(int id, string name)
        {
            ID = id;
            Name = name;
        }
    }
基本用法
スポンサーリンク
C#プログラミング再入門