开放的编程资料库

当前位置:我爱分享网 > C#教程 > 正文

C#构造函数

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;
}

在构造方法中,我们初始化了两个属性:NameBorn。由于属性和构造函数参数的名称相同,因此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构造函数参数名称,它们不同于NameBorn属性,我们可以省略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数据类型的默认值为空字符串,DateTimeDateTime.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#教程。

未经允许不得转载:我爱分享网 » C#构造函数

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏