Как правильно использовать :base() и :this()?

Я уже искал эту проблему как на SO, так и на других веб-сайтах, но мне не удалось найти (или найти) решение для моего случая.

У меня есть абстрактный класс EnteBase, который я использую в качестве основы (да!) для двух других классов, Regione и Provincia.


EnteBase:

public abstract class EnteBase
{
    public EnteBase ()
        : this( "Sconosciuto", 0 )
    {
    }

    public EnteBase ( string nome )
        : this( nome, 0 )
    {
    }

    public EnteBase ( string nome, int numeroComuni )
    {
        this.Nome = nome;
        this.NumeroComuni = numeroComuni;
    }


    private string nome;
    public string Nome
    {
        [...]
    }

    private int numeroComuni;
    public int NumeroComuni
    {
        [...]
    }
}

Regione:

public class Regione : EnteBase
{
    public List<Provincia> Province
    {
        [...]
    }


    public Regione ()
        : base()
    {
        this.Province = new List<Provincia>();
    }

    public Regione ( string nome )
        : this()
    {
    }

    public Regione ( string nome, int numeroComuni )
        : this()
    {
    }


    public void AggiungiProvincia ( Provincia provincia )
    {
        Province.Add( provincia );
    }
}

Provincia:

public class Provincia : EnteBase
{
    private string sigla;

    public string Sigla
    {
        [...]
    }

    public Provincia ()
        : base()
    {
    }

    public Provincia ( string nome )
        : this()
    {
        this.Nome = nome;
    }

    public Provincia ( string nome, int numeroComuni )
        : this()
    {
        this.Nome = nome;
        this.NumeroComuni = numeroComuni;
    }

    public Provincia( string nome, int numeroComuni, string sigla)
        : this()
    {
        this.Nome = nome;
        this.NumeroComuni = numeroComuni;
        this.Sigla = sigla;
    }
}

Мои вопросы следующие:

  • Правильно ли использовать :this() во всех конструкторах базового класса, кроме одного с наибольшим количеством параметров, а остальные указывают на последнего?
  • Правильно ли использовать :this(), указывающий на базовый конструктор в классах Provincia и Regione, а затем назначать поля внутри самого метода?

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

P.S.: в конструкторах предпочтительнее использовать this.FieldName или только FieldName?


person Gabriele Cirulli    schedule 04.02.2012    source источник
comment
Я думаю, вы забыли скопировать инициализацию поля в конструктор Regione.   -  person    schedule 05.02.2012
comment
@hvd Спасибо, я случайно пропустил это   -  person Gabriele Cirulli    schedule 05.02.2012


Ответы (3)


Правильно ли использовать :this() во всех конструкторах базового класса, кроме одного с наибольшим количеством параметров, а остальные указывают на последний?

Единственный вариант использования - цепочка конструкторов, когда вы минимизируете свою работу по инициализации до одного конструктора и заставляете все остальные конструкторы использовать this() с параметрами, которые вызывают выполнение этого конструктора - вы делаете именно это уже в своем классе EnteBase.

Пустой вызов base() обычно бесполезен, так как базовый конструктор по умолчанию все равно вызывается по умолчанию.

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

person BrokenGlass    schedule 04.02.2012

Правильно ли использовать :this(), указывающий на базовый конструктор в классах Provincia и Regione, а затем назначать поля внутри самого метода?

В C# вызов :base() является неявным, поэтому его не нужно делать явно.

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

Правильно ли использовать :this() во всех конструкторах базового класса, кроме одного с наибольшим количеством параметров, а остальные указывают на последний?

Да, это распространенный способ придания значениям разумных значений по умолчанию.

person Rich O'Kelly    schedule 04.02.2012
comment
Ваш первый ответ все еще действителен для класса Regione теперь, когда я использовал конструктор без параметров для инициализации this.Province? Если нет, то что должно измениться? - person Gabriele Cirulli; 05.02.2012
comment
@GabrieleCirulli Вам нужно будет сохранить вызов :this() или, альтернативно, инициализировать вспомогательное поле для встроенного свойства. - person Rich O'Kelly; 05.02.2012
comment
это обычное private List<Provincia> province = new List<Provincia>()? - person Gabriele Cirulli; 05.02.2012
comment
@GabrieleCirulli Да, ты понял! - person Rich O'Kelly; 05.02.2012

Вы должны изменить следующие Constructor в subclass из:

public Provincia ( string nome, int numeroComuni )
    : this()
{
    this.Nome = nome;
    this.NumeroComuni = numeroComuni;
}

Кому:

public Provincia ( string nome, int numeroComuni )
    : base(nome, numeroComuni)
{
}

И то же самое в следующем Constructor из:

public Provincia( string nome, int numeroComuni, string sigla)
    : this()
{
    this.Nome = nome;
    this.NumeroComuni = numeroComuni;
    this.Sigla = sigla;
}

Кому:

public Provincia( string nome, int numeroComuni, string sigla)
    : base(nome, numeroComuni)
{
    this.Sigla = sigla;
}

Устранение необходимости устанавливать свойства superclass в subclass, как это предусмотрено реализацией superclasses.

person xandercoded    schedule 04.02.2012