C#构造函数教程展示了如何使用C#语言中的构造函数。
构造函数是在创建对象时调用的方法。类、结构和记录都有构造函数。构造函数的目的是启动对象的状态。
构造函数不返回值,也不使用void
关键字。它与类同名。构造函数可以重载;即可以有多个具有不同参数的构造函数(具有相同的名称)。
构造函数不能被继承。它们按照继承的顺序被调用。如果我们不为类编写任何构造函数,C#提供了一个隐式的默认构造函数。如果我们提供任何类型的构造函数,则不提供默认值。
构造函数不能是抽象的、最终的和同步的。
C#构造函数示例
构造函数用于初始化字段。
var name = "Lenka"; var dob = new DateTime(1990, 3, 5); var u = new User(name, dob); Console.WriteLine(u); class User { private DateTime Born; private string Name; public User(string Name, DateTime Born) { this.Name = Name; this.Born = Born; } public override string ToString() => $"{this.Name} was born on {this.Born.ToShortDateString()}"; }
User
类有一个构造函数。
var u = new User(name, dob);
我们创建了User
对象,给它的构造函数传递了两个值。这是调用对象的构造函数的时候。
public User(string Name, DateTime Born) { this.Name = Name; this.Born = Born; }
在构造方法中,我们初始化了两个属性:Name
和Born
。由于属性和构造函数参数的名称相同,因此this关键字是必需的。用于引用类的属性。
$ dotnet run Lenka was born on 3/5/1990
如果我们为构造函数参数使用不同的名称,则不需要this
关键字。
var name = "Lenka"; var dob = new DateTime(1990, 3, 5); var u = new User(name, dob); Console.WriteLine(u); class User { private DateTime Born; private string Name; public User(string _Name, DateTime _Born) { Name = _Name; Born = _Born; } public override string ToString() => $"{this.Name} was born on {this.Born.ToShortDateString()}"; }
由于我们使用了_Name
和_Born
构造函数参数名称,它们不同于Name
和Born
属性,我们可以省略this
关键字。
C#默认构造函数
默认构造函数是不接受任何参数的构造函数。
如果我们不提供任何构造函数,C#会默认创建一个实例化对象并将成员变量设置为默认值的构造函数。
var u = new User(); Console.WriteLine(string.IsNullOrEmpty(u.Name)); Console.WriteLine(string.IsNullOrEmpty(u.Occupation)); Console.WriteLine(string.IsNullOrEmpty(u.Dob.ToString())); Console.WriteLine(u); class User { public string Name { get; set; } public string Occupation { get; set; } public DateTime Dob { get; set; } public override string ToString() => $"User {{ {this.Name} {this.Occupation} {this.Dob} }}"; }
我们有一个User
类;我们不提供自己的构造函数,因此C#创建了一个默认构造函数。string
数据类型的默认值为空字符串,DateTime
为DateTime.MinValue
。
$ dotnet run True True False User { 1/1/0001 12:00:00 AM }
C#重载构造函数
构造函数可以重载。
var u1 = new User(); var u2 = new User("Tom"); class User { public User() { Console.WriteLine("User is created"); } public User(string name) { Console.WriteLine($"User {name} is created"); } }
User
类中有两个构造函数。C#根据我们传递给它们的参数调用这些构造函数。
如果我们提供自定义构造函数,C#不会创建默认构造函数。我们可以显式创建一个默认的无参数构造函数。
var u1 = new User();
此处调用默认的无参数构造函数。
var u2 = new User("Tom");
这里调用了带一个参数的第二个构造函数。
$ dotnet run User is created User Tom is created
C#expression-bodiedconstructor
我们可以创建表达式主体的构造函数。对于短构造函数,它们提供了更简洁、更美观的语法。
var u1 = new User("John Doe", "gardener"); var u2 = new User("Roger Roe", "driver"); Console.WriteLine(u1); Console.WriteLine(u2); class User { private string Name; private string Occupation; public User(string Name, string Occupation) => (this.Name, this.Occupation) = (Name, Occupation); public override string ToString() => $"User {{ {this.Name} {this.Occupation} }}"; }
我们有一个带有两个参数的构造函数;它们被设置在表达式主体中。
public User(string Name, string Occupation) => (this.Name, this.Occupation) = (Name, Occupation);
在这种情况下,this
关键字是必需的。
C#构造函数链
构造函数链接是类从构造函数调用另一个构造函数的能力。要从同一个类调用另一个构造函数,我们使用this
关键字。
var c1 = new Circle(5); var c2 = new Circle(); class Circle { public Circle(int radius) { Console.WriteLine($"Circle, r={radius} is created"); } public Circle() : this(1) { } }
我们有一个Circle
类。该类有两个构造函数:第一个带一个参数,第二个不带任何参数。
public Circle(int radius) { Console.WriteLine("Circle, r={0} is created", radius); }
此构造函数采用一个参数——radius
。
public Circle() : this(1) { }
这是没有参数的构造函数。它只是调用另一个构造函数并为其指定默认半径1。
$ dotnet run Circle, r=5 is created Circle, r=1 is created
C#基类构造函数
派生类实例化时会自动调用基类构造函数。
var u1 = new User(); Console.WriteLine("---------------"); var u2 = new User("Tom"); class Base { public Base() { Console.WriteLine("Base constructor called"); } } class User : Base { public User() { Console.WriteLine("User constructor called"); } public User(string user) { Console.WriteLine($"User {user} created"); } }
User
类继承自Base
类。两个构造函数都调用基类构造函数。
$ dotnet run Base constructor called User constructor called --------------- Base constructor called User Tom created
使用base
关键字,我们可以指定在创建派生类的实例时应调用哪个基类构造函数。
var u1 = new User(); Console.WriteLine("---------------"); var u2 = new User("Tom"); class Base { public Base() { Console.WriteLine("Base() called"); } public Base(string name) { Console.WriteLine("Base(string name) called"); } } class User : Base { public User() { Console.WriteLine("User created"); } public User(string name) : base(name) { Console.WriteLine($"User {name} created"); } }
现在Base
类有两个构造函数。我们可以使用base
关键字指定要调用的构造函数。
public User(string name) : base(name) { Console.WriteLine($"User {name} created"); }
我们告诉构造函数调用带一个参数的基本构造函数。
$ dotnet run Base() called User created --------------- Base(string name) called User Tom created
C#拷贝构造函数
通过从另一个对象复制变量来创建对象的构造函数称为复制构造函数。
var u1 = new User("John Doe", "gardener"); var u2 = new User(u1); u2.Name = "Roger Roe"; Console.WriteLine(u1); Console.WriteLine(u2); class User { public string Name { get; set; } public string Occupation { get; set; } public User(string Name, string Occupation) => (this.Name, this.Occupation) = (Name, Occupation); public User(User user) { this.Name = user.Name; this.Occupation = user.Occupation; } public override string ToString() => $"User {{ {this.Name} {this.Occupation} }}"; }
User
类包含一个复制构造函数。
public User(User user) { this.Name = user.Name; this.Occupation = user.Occupation; }
类的属性是从作为参数传递给构造函数的对象中赋值的。
$ dotnet run User { John Doe gardener } User { Roger Roe gardener }
C#私有构造函数
其他类不能创建具有私有构造函数的类的实例。私有构造函数通常用于只有静态成员的类。
Console.WriteLine(MyMath.Pow(2)); Console.WriteLine(MyMath.Pow(2, 3)); Console.WriteLine(MyMath.Pow(2, 5)); // var mm = new MyMath(); // Console.WriteLine(mm.GetType()); class MyMath { private MyMath() { } public static int Pow(int x, int y = 2) { int val = 1; for (int i = 0; i < y; i++) { val *= x; } return val; } }
我们有一个包含唯一静态成员的MyMath
类。它被设计为在不创建其实例的情况下使用——私有构造函数禁止这样做。
$ dotnet run 4 8 32
C#静态构造函数
静态构造函数用于初始化静态数据或执行只需执行一次的操作。在创建第一个实例或引用任何静态成员之前自动调用它。
var runner1 = new Runner(1); Thread.Sleep(700); var runner2 = new Runner(2); Thread.Sleep(1100); Console.WriteLine(runner1.Finish()); Console.WriteLine(runner2.Finish()); class Runner { private static readonly DateTime StartTime; private long Id; static Runner() => StartTime = DateTime.Now; public Runner(long Id) => this.Id = Id; public string Finish() { DateTime EndTime = DateTime.Now; return $"Runner {this.Id} finished in {EndTime - StartTime}"; } }
我们有一个名为StartTime
的静态只读变量。当创建第一个Runner
时,它使用静态构造函数启动。
static Runner() => StartTime = DateTime.Now;
初始化后,静态StartTime
可用于Runner
的所有实例。
$ dotnet run Runner 1 finished in 00:00:01.8267889 Runner 2 finished in 00:00:01.8900243
在本文中,我们使用了C#中的构造函数。
列出所有C#教程。