使用 this 链接构造函数
在多个构造函数之间复用初始化逻辑。
使用 this 链接构造函数 是 CoddyKit 上的免费 C# Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。
为什么要链式调用构造函数
当多个构造函数共享设置逻辑时,您可以将它们链式调用,让一个构造函数调用另一个构造函数。这样可以避免重复代码,并将初始化逻辑集中在一个位置。
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);
}
}: this(...) 语法
链式调用会在构造函数签名后使用 : 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();
}
}唯一真实来源
让所有构造函数都汇集到一个包含实际逻辑的“主要”构造函数中。其他构造函数只需提供默认值并将调用链指向它。
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);
}
}使用默认值进行链式调用
链式调用是表达分层默认值的一种简洁方式:每个参数更少的构造函数再补充一个默认值,然后委托给下一个构造函数。
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:一个构造函数负责验证和赋值,其余构造函数提供便捷的简写方式。
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) 调用同一个类中的另一个构造函数。目标构造函数先运行,然后才运行当前构造函数的主体。让每个构造函数都经过一个主要构造函数,可以集中处理验证并避免重复设置。不允许循环调用链。
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 链接构造函数」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。
「使用 this 链接构造函数」这节课中我会学到什么?
在多个构造函数之间复用初始化逻辑。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C# Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「使用 this 链接构造函数」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C# Academy 课中编写并运行代码吗?
能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。