1. ホーム 
  2. 備忘録 
  3. C Sharp

オブジェクト初期化子

オブジェクト初期化子

オブジェクト初期化子を使用すると、オブジェクトの作成時にアクセスできるフィールドまたはプロパティに、コンストラクターを呼び出して代入ステートメントを使用しなくても、値を割り当てることができる

オブジェクト初期化子の構文では、コンストラクターの引数を指定することも、引数 (およびかっこ構文) を省略することもできる

public class Cat
{
    // Auto-implemented properties.
    public int Age { get; set; }
    public string? Name { get; set; }

    public Cat()
    {
    }

    public Cat(string name)
    {
        this.Name = name;
    }
}

Cat cat = new Cat { Age = 10, Name = "Fluffy" };
Cat sameCat = new Cat("Fluffy"){ Age = 10 };

オブジェクト初期化子では、フィールドとプロパティを割り当てることに加え、インデクサーを設定できる

public class Matrix
{
    private double[,] storage = new double[3, 3];

    public double this[int row, int column]
    {
        // The embedded array will throw out of range exceptions as appropriate.
        get { return storage[row, column]; }
        set { storage[row, column] = value; }
    }
}

var identity = new Matrix
{
    [0, 0] = 1.0,
    [0, 1] = 0.0,
    [0, 2] = 0.0,

    [1, 0] = 0.0,
    [1, 1] = 1.0,
    [1, 2] = 0.0,

    [2, 0] = 0.0,
    [2, 1] = 0.0,
    [2, 2] = 1.0,
};

匿名型での利用

オブジェクト初期化子は、どのような場合にも使うことができるが、LINQ クエリ式で使うと特に有用である

class Program
{
    static void Main()
    {
        // Productクラスにはいらない要素がいっぱいある
        List<Products> products = new List<Products>()
        {
            new Products { ProductId = 1, ProductName = "test1", UnitPrice = 100, ProductOwnerName = "Tarou" },
            new Products { ProductId = 2, ProductName = "test2", UnitPrice = 200, ProductOwnerName = "Jirou"  },
            new Products { ProductId = 3, ProductName = "test3", UnitPrice = 300, ProductOwnerName = "Saburou" },
            new Products { ProductId = 4, ProductName = "test4", UnitPrice = 400, ProductOwnerName = "Shirou" },
        };
        
        // 必要な要素のみを持った匿名クラスを作成する
        // 基本的に元のオブジェクトのプロパティまたはフィールド名と同じ名前がつけられるが、下記のように変更することもできる
        var productInfos = 
            from p in products
            select new { p.ProductName, Price = p.UnitPrice };

        foreach ( var productInfo in productInfos )
        {
            Console.WriteLine( productInfo );
        }

        // 結果
        // { ProductName = test1, Price = 100 }
        // { ProductName = test2, Price = 200 }
        // { ProductName = test3, Price = 300 }
        // { ProductName = test4, Price = 400 }
    }
}

class Products
{
    public int ProductId { get; set; }
    public string? ProductName { get; set; }
    public int UnitPrice { get; set; }
    public string? ProductOwnerName { get; set; }
}

required 修飾子

required キーワードを使用することで、呼び出し元がオブジェクト初期化子を使用して、プロパティまたはフィールドの値を設定するよう強制できる

コンパイラは、すべての呼び出し元がこれらの値を初期化することを保証するため、必須のプロパティをコンストラクタパラメーターとして設定する必要はない

管理するフィールドまたはプロパティが多く、それらの初期化が必須な場合に、コンストラクタが肥大化してしまうのを防ぐことができる


init 修飾子

init アクセサーを使用して、設計されたオブジェクトを誰も変更できないように制限できる

class Program
{
    static void Main()
    {
        // オブジェクト初期化子で init キーワードつきのプロパティは書き換えられる
        var person = new Person() { FirstName = "Tarou", LastName = "Yamada" };

        // 書き換え可能
        person.FirstName = "Jirou";

        // init キーワードがついているので後から変更できない
        // person.LastName = "Suzuki";
    }
}

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; init; }
}

    参考文献

  1. オブジェクト初期化子とコレクション初期化子