thisによるコンストラクターの連鎖
コンストラクター間で初期化処理を再利用します。
「thisによるコンストラクターの連鎖」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。
コンストラクターをチェーンする理由
複数のコンストラクターでセットアップ処理を共有する場合は、一方からもう一方を呼び出すようにチェーンできます。これによりコードの重複を避け、初期化処理を1か所にまとめられます。
using System;
class Box
{
public int Width;
public int Height;
public Box(int width, int height)
{
Width = width;
Height = height;
}
public Box() : this(1, 1) { }
}
class Program
{
static void Main()
{
var def = new Box();
Console.WriteLine(def.Width + "x" + def.Height);
}
}<code>: this(...)</code> 構文
チェーンには、コンストラクターのシグネチャの後に : this(args) を記述します。対象のコンストラクターが先に実行され、その後で現在のコンストラクターの本体が実行されます。
using System;
class Person
{
public string Name;
public int Age;
public Person(string name, int age)
{
Name = name;
Age = age;
Console.WriteLine("Full constructor ran");
}
public Person(string name) : this(name, 0)
{
Console.WriteLine("Name-only constructor ran");
}
}
class Program
{
static void Main()
{
var p = new Person("Sam");
Console.WriteLine(p.Name + ", " + p.Age);
}
}実行順序
呼び出し元のコンストラクターの本体より先に、チェーンされたコンストラクターが実行されます。これにより、基礎となるセットアップが必ず先に行われます。
using System;
class Step
{
public Step(int n)
{
Console.WriteLine("Init with " + n);
}
public Step() : this(0)
{
Console.WriteLine("Then default body");
}
}
class Program
{
static void Main()
{
var s = new Step();
}
}信頼できる唯一の情報源
すべてのコンストラクターを、実際のロジックを持つ1つの「主要」コンストラクターに集約します。それ以外のコンストラクターは既定値を指定して、そこへチェーンするだけにします。
using System;
class Connection
{
public string Host;
public int Port;
public Connection(string host, int port)
{
Host = host;
Port = port;
}
public Connection(string host) : this(host, 8080) { }
public Connection() : this("localhost", 8080) { }
}
class Program
{
static void Main()
{
var c = new Connection("example.com");
Console.WriteLine(c.Host + ":" + c.Port);
}
}既定値を使ったチェーン
チェーンを使うと、段階的な既定値をわかりやすく表現できます。それぞれの短いコンストラクターが追加の既定値を1つ設定し、処理を委譲します。
using System;
class Coffee
{
public string Size;
public bool Milk;
public int Sugar;
public Coffee(string size, bool milk, int sugar)
{
Size = size;
Milk = milk;
Sugar = sugar;
}
public Coffee(string size, bool milk) : this(size, milk, 0) { }
public Coffee(string size) : this(size, false) { }
}
class Program
{
static void Main()
{
var c = new Coffee("large");
Console.WriteLine(c.Size + ", milk=" + c.Milk + ", sugar=" + c.Sugar);
}
}対象側での検証
すべてのコンストラクターが主要コンストラクターを経由するため、そこに記述した検証によって、すべての生成経路を保護できます。
using System;
class Rect
{
public int W;
public int H;
public Rect(int w, int h)
{
if (w <= 0 || h <= 0)
throw new ArgumentException("Dimensions must be positive");
W = w;
H = h;
}
public Rect(int side) : this(side, side) { }
}
class Program
{
static void Main()
{
var square = new Rect(5);
Console.WriteLine(square.W + "x" + square.H);
}
}チェーンと既定のパラメーター
既定のパラメーターを使えば多くのオーバーロードを置き換えられますが、それぞれのコンストラクターの本体で少しずつ異なる処理が必要な場合は、チェーンのほうが明確です。
using System;
class Logger
{
public string Prefix;
public bool Verbose;
public Logger(string prefix, bool verbose)
{
Prefix = prefix;
Verbose = verbose;
}
public Logger(string prefix) : this(prefix, false)
{
Console.WriteLine("Created quiet logger");
}
}
class Program
{
static void Main()
{
var log = new Logger("APP");
Console.WriteLine(log.Prefix + " verbose=" + log.Verbose);
}
}空の本体は一般的です
チェーンするコンストラクターでは、すべての処理が対象側で行われるため、{ } の本体が空になることがよくあります。
using System;
class Vector
{
public double X, Y, Z;
public Vector(double x, double y, double z)
{
X = x; Y = y; Z = z;
}
public Vector(double v) : this(v, v, v) { }
}
class Program
{
static void Main()
{
var v = new Vector(2);
Console.WriteLine(v.X + "," + v.Y + "," + v.Z);
}
}循環の回避
コンストラクターをループ状にチェーンしてはいけません(A が B を呼び出し、B が A を呼び出す状態です)。コンパイラーは循環する : this(...) のチェーンを拒否します。
using System;
class Safe
{
public int A, B;
public Safe(int a, int b)
{
A = a;
B = b;
}
public Safe(int a) : this(a, 0) { } // chains one direction only
}
class Program
{
static void Main()
{
var s = new Safe(7);
Console.WriteLine(s.A + ", " + s.B);
}
}this.field との組み合わせ
チェーンを使う場合でも、本体で this. を使って、対象のコンストラクターから戻った後に追加のセットアップを行えます。
using System;
class Account
{
public string Owner;
public decimal Balance;
public bool Active;
public Account(string owner, decimal balance)
{
this.Owner = owner;
this.Balance = balance;
}
public Account(string owner) : this(owner, 0m)
{
this.Active = true;
}
}
class Program
{
static void Main()
{
var a = new Account("Rin");
Console.WriteLine(a.Owner + " active=" + a.Active);
}
}まとめてみましょう
チェーンを使うと、クラスを DRY に保てます。1つのコンストラクターで検証と代入を行い、それ以外のコンストラクターは便利な短縮記法を提供します。
using System;
class Pizza
{
public string Size;
public int Toppings;
public Pizza(string size, int toppings)
{
if (toppings < 0) throw new ArgumentException("toppings");
Size = size;
Toppings = toppings;
}
public Pizza(string size) : this(size, 0) { }
public Pizza() : this("medium") { }
}
class Program
{
static void Main()
{
var p = new Pizza();
Console.WriteLine(p.Size + " with " + p.Toppings + " toppings");
}
}理解度チェック
コンストラクターのチェーンについての理解度を確認しましょう。
まとめ
コンストラクターのチェーンでは、: this(args) を使って同じクラス内の別のコンストラクターを呼び出します。対象のコンストラクターが先に実行され、その後で現在の本体が実行されます。すべてのコンストラクターを1つの主要コンストラクターに通すことで、検証を一元化し、セットアップ処理の重複を避けられます。循環するチェーンは使用できません。
using System;
class Demo
{
public int X, Y;
public Demo(int x, int y) { X = x; Y = y; }
public Demo(int both) : this(both, both) { }
}
class Program
{
static void Main()
{
var d = new Demo(4);
Console.WriteLine(d.X + "," + d.Y);
}
}よくある質問
「thisによるコンストラクターの連鎖」レッスンは無料ですか?
はい。「thisによるコンストラクターの連鎖」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。
「thisによるコンストラクターの連鎖」で何を学びますか?
コンストラクター間で初期化処理を再利用します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C# Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「thisによるコンストラクターの連鎖」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC# Academyレッスンでコードを書いて実行できますか?
はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- コンストラクターの定義
- thisによるコンストラクターの連鎖
- オブジェクトとコレクションの初期化子
- 静的コンストラクター