base() 和 this() 构造函数最佳实践

Posted

技术标签:

【中文标题】base() 和 this() 构造函数最佳实践【英文标题】:base() and this() constructors best practices 【发布时间】:2011-04-17 09:16:41 【问题描述】:

在什么条件下我应该在构造函数的括号之后(甚至在代码中的其他位置)进行 :base():this() 构造函数调用。这些电话什么时候是好的做法,什么时候是强制性的?

【问题讨论】:

抱歉含糊不清......我知道这些电话在做什么。我只是不清楚我应该或必须拨打这些电话的情况。如果我不制作它们,那么我马上就注定要失败,或者会有潜在的错误,或者代码质量差。我最近很头疼,因此我想澄清这些情况。 —— 【参考方案1】:

: base(...)

如果您省略对基构造函数的调用,它将自动调用默认基构造函数。

如果没有默认构造函数,则必须显式调用基本构造函数。

即使存在默认构造函数,您仍可能希望调用与默认构造函数不同的构造函数。在这种情况下,您可能仍希望使用base(foo, bar) 来调用与基本构造函数不同的构造函数。

我不认为当你想调用基类默认构造函数时省略base() 是一个坏习惯,尽管如果你想明确一点,我认为包含它并没有什么坏处。这是一个品味问题。

: this(...)

此语法允许您在同一类中调用具有不同签名的构造函数。这样做从来都不是强制性的,但有时会很有用。

一个有用的例子是在构造函数中重用公共代码。例如,在 C# 3.5 或之前,您可能希望在构造函数上模拟可选参数:

Foo(int x, int y)

     this.x = x;
     this.y = y;


Foo(int x) : this(x, 10)   // y defaults to 10

现在可以使用 C# 4.0 可选参数,这减少了对这种方法的需求。

在构造函数中重用代码的另一种方法是将其分解为一个静态函数,该函数从每个希望使用它的构造函数中调用。

【讨论】:

【参考方案2】:

首先,当它们是强制性的时。

当类Derived 派生自类Base,并且Base 没有默认(无参数)构造函数时,Derived 必须显式调用base() 并带参数。

public class Base 
    public Base(int i)  



public class Derived : Base 
    // public Derived()   wouldn't work - what should be given for i?
    public Derived() : base(7)  
    public Derived(int i) : base(i)  


什么时候是好的做法?每当您想调用不同的构造函数时。

假设您在我之前的示例中将内容添加到 Derived 中的构造函数。

public class Derived : Base 
    // public Derived()   wouldn't work - what should be given for i?
    public Derived() : base(7) 
        Console.WriteLine("The value is " + 7);
    
    public Derived(int i) : base(i) 
        Console.WriteLine("The value is " + i);
    

你注意到这里的重复了吗?调用 this() 构造函数更简单。

public class Derived : Base 
    // public Derived()   wouldn't work - what should be given for i?
    public Derived() : this(7)  
    public Derived(int i) : base(i) 
        Console.WriteLine("The value is " + i);
    

【讨论】:

所以最后一个例子中的调用顺序是:base(7),然后是Derived(7),然后是Derived()。换句话说,this(7) 部分本身不会触发base()(假设有这样的基本方法)。对吗? 正确;构造函数总是链式的,每个类都调用其基类的构造函数。使用this,你可以重用这个类的另一个构造函数(它本身将使用base,或者隐式地不带参数或显式地使用);使用base,您可以选择调用哪个基类构造函数。【参考方案3】:

当存在继承时使用base,并且父类已经提供了您想要实现的功能。

当您想要引用当前实体(或自身)时使用this,当您不想复制已经在另一个构造函数中定义的功能时,在构造函数的标头/签名中使用它。

基本上,在构造函数的标头中使用 base 和 this 是为了让您的代码保持 DRY,使其更易于维护且不那么冗长

这是一个绝对没有意义的例子,但我认为它说明了展示如何使用这两者的想法。

class Person

    public Person(string name)
    
        Debug.WriteLine("My name is " + name);
    


class Employee : Person

    public Employee(string name, string job)
        : base(name)
    
        Debug.WriteLine("I " + job + " for money.");
    

    public Employee() : this("Jeff", "write code")
    
        Debug.WriteLine("I like cake.");
    

用法:

var foo = new Person("ANaimi");
// output:
//  My name is ANaimi

var bar = new Employee("ANaimi", "cook food");
// output:
//  My name is ANaimi
//  I cook food for money.

var baz = new Employee();
// output:
//  My name is Jeff
//  I write code for money.
//  I like cake.

【讨论】:

【参考方案4】:

查找“C# 中的构造函数链接”。基本上,它看起来像这样:

MyClass():base()  //default constructor calling superclass constructor



MyClass(int arg):this()  //non-basic constructor calling base constructor

    //extra initialization

它有助于消除构造函数中的代码重复 - 将它们分成基本部分和特定部分。

【讨论】:

谢谢。 “构造函数链”这个词我不记得了。【参考方案5】:

当您希望将基类的构造函数作为构造函数的第一条指令自动调用时,您可以使用 :base()。 :this() 类似,但它调用同一个类的另一个构造函数。

在 base:() 和 this() 中:您可以将常量值或基于构造函数参数的表达式作为参数传递。

当基类没有默认构造函数(不带参数的构造函数)时,必须调用基构造函数。我不知道 :this() 是强制性的。

public class ABaseClass

    public ABaseClass(string s) 


public class Foo : AChildClass

    public AChildClass(string s) : base(s)  //base mandatory
    public AChildClass() : base("default value")   //base mandatory
    public AChildClass(string s,int i) : base(s+i)   //base mandatory


public class AnotherBaseClass

    public ABaseClass(string s) 
    public ABaseClass():this("default value")  //call constructor above


public class Foo : AnotherChildClass

    public AnotherChildClass(string s) : base(s)  //base optional


【讨论】:

以上是关于base() 和 this() 构造函数最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

构造函数重载 - Java 中的最佳实践 [关闭]

构造函数和析构函数中的虚函数调用[重复]

C++基础——C++面向对象之类对象与继承基础总结(类和对象概念构造函数与析构函数this指针继承)

C++ 继承中构造和析构对象(面试题可能问)

在构造函数/析构函数中能否调用虚函数?

c#学习-base和this在构造函数中的应用