代码之家  ›  专栏  ›  技术社区  ›  explorer

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

  •  73
  • explorer  · 技术社区  · 14 年前

    我应该在什么条件下 :base() :this() 构造函数调用在我的构造函数的圆括号后面(甚至在代码的其他地方)。什么时候称之为良好实践,什么时候强制?

    5 回复  |  直到 7 年前
        1
  •  97
  •   Community Ian Goodfellow    9 年前

    : 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
  •  31
  •   David Glass    11 年前

    首先,当他们是强制性的。

    当一个班 Derived 是从类派生的 Base 基地 没有默认(无参数)构造函数, 派生 必须呼叫 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) { }
    }
    

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

    假设您在前面的示例中向派生的构造函数添加内容。

    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);
        }
    }
    
        3
  •  27
  •   ANaimi    14 年前

    使用 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
  •  8
  •   alxx    14 年前

    寻找“C_中的构造函数链接”。基本上是这样的:

    MyClass():base()  //default constructor calling superclass constructor
    {
    }
    
    MyClass(int arg):this()  //non-basic constructor calling base constructor
    {
        //extra initialization
    }
    

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

        5
  •  4
  •   Robert Oschler Rob    11 年前

    当您希望将基类的构造函数自动调用为构造函数的第一条指令时,可以使用: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
    
    }