Base() и this() лучшие методы

В каких условиях я должен создавать вызовы конструктора :base() и :this(), следующие за скобками конструктора (или даже в других местах кода). Когда эти вызовы являются хорошей практикой и когда они являются обязательными?

Ответ 1

: base(...)

Если вы опустите вызов базовому конструктору, он автоматически вызовет базовый конструктор по умолчанию.

Обязательно вызывать базовый конструктор явно, если нет конструктора по умолчанию.

Даже если есть конструктор по умолчанию, вы все равно можете вызвать другой конструктор, чем конструктор по умолчанию. В этом случае вы все равно можете использовать base(foo, bar) для вызова другого конструктора, чем базовый конструктор.

Я не считаю плохой практикой опускать base(), когда вы хотите вызвать конструктор по умолчанию базового класса, хотя, если вам нравится быть явным, я не вижу вреда в его включении. Это вопрос вкуса.

: this(...)

Этот синтаксис позволяет вызывать один конструктор с другой подписью от другого в пределах одного класса. Это никогда не обязательно делать, но иногда может быть полезно.

Примером того, когда это может быть полезно, является повторное использование общего кода в конструкторах. Например, в С# 3.5 или до того, как вы захотите моделировать необязательные параметры для конструктора:

Foo(int x, int y)
{
     this.x = x;
     this.y = y;
}

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

Теперь доступны дополнительные параметры С# 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);
    }
}

Вы заметили дублирование здесь? Проще назвать этот конструктор().

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

Используйте 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

Вы используете: base(), когда вы хотите, чтобы конструктор базового класса автоматически вызывался как первая инструкция вашего конструктора.: this() он похож, но он вызывает другой конструктор в том же классе.

В базе:() и 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

}

Ответ 5

Найдите "цепочку конструкторов в С#". В основном это выглядит так:

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

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

Это помогает удалить дублирование кода в конструкторах - разбить их на основные и конкретные части.