Вызов одного конструктора из другого - PullRequest
885 голосов
/ 24 октября 2010

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

class Sample
{
    public Sample(string theIntAsString)
    {
        int i = int.Parse(theIntAsString);

        _intField = i;
    }

    public Sample(int theInt)
    {
        _intField = theInt;
    }


    public int IntProperty
    {
        get { return _intField; }
    }
    private readonly int _intField;

}

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

Теперь вот в чем загвоздка:

  1. Я не хочу дублировать код настройки.В этом случае установлено только одно поле, но, конечно, может быть и более одного.
  2. Чтобы сделать поля доступными только для чтения, мне нужно установить их из конструктора, поэтому я не могу "извлечь"общий код для служебной функции.
  3. Я не знаю, как вызвать один конструктор из другого.

Есть идеи?

Ответы [ 8 ]

1474 голосов
/ 24 октября 2010

Как это:

public Sample(string str) : this(int.Parse(str)) {
}
152 голосов
/ 23 июля 2011

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

class Sample
{
    private readonly int _intField;
    public int IntProperty
    {
        get { return _intField; }
    }

    void setupStuff(ref int intField, int newValue)
    {
        intField = newValue;
    }

    public Sample(string theIntAsString)
    {
        int i = int.Parse(theIntAsString);
        setupStuff(ref _intField,i);
    }

    public Sample(int theInt)
    {
        setupStuff(ref _intField, theInt);
    }
}
56 голосов
/ 24 октября 2010

Перед телом конструктора используйте:

: base (parameters)

: this (parameters)

Пример:

public class People: User
{
   public People (int EmpID) : base (EmpID)
   {
      // Add more statements here.
   }
}
9 голосов
/ 28 ноября 2012

Я улучшаю ответ суперкатера. Я думаю, что можно сделать следующее:

class Sample
{
    private readonly int _intField;
    public int IntProperty
    {
        get { return _intField; }
    }

    void setupStuff(ref int intField, int newValue)
    {
        //Do some stuff here based upon the necessary initialized variables.
        intField = newValue;
    }

    public Sample(string theIntAsString, bool? doStuff = true)
    {
        //Initialization of some necessary variables.
        //==========================================
        int i = int.Parse(theIntAsString);
        // ................
        // .......................
        //==========================================

        if (!doStuff.HasValue || doStuff.Value == true)
           setupStuff(ref _intField,i);
    }

    public Sample(int theInt): this(theInt, false) //"false" param to avoid setupStuff() being called two times
    {
        setupStuff(ref _intField, theInt);
    }
}
6 голосов
/ 23 мая 2014

Вот пример, который вызывает другой конструктор, а затем проверяет установленное свойство.

    public SomeClass(int i)
    {
        I = i;
    }

    public SomeClass(SomeOtherClass soc)
        : this(soc.J)
    {
        if (I==0)
        {
            I = DoSomethingHere();
        }
    }
4 голосов
/ 07 июня 2016

Да, вы можете вызывать другой метод перед базой вызовов или этим!

public class MyException : Exception
{
    public MyException(int number) : base(ConvertToString(number)) 
    {
    }

    private static string ConvertToString(int number) 
    { 
      return number.toString()
    }

}
1 голос
/ 31 марта 2015

Когда вы наследуете класс от базового класса, вы можете вызвать конструктор базового класса, создав экземпляр производного класса

class sample
{
    public int x;

    public sample(int value)
    {
        x = value;
    }
}

class der : sample
{
    public int a;
    public int b;

    public der(int value1,int value2) : base(50)
    {
        a = value1;
        b = value2;
    }
}

class run 
{
    public static void Main(string[] args)
    {
        der obj = new der(10,20);

        System.Console.WriteLine(obj.x);
        System.Console.WriteLine(obj.a);
        System.Console.WriteLine(obj.b);
    }
}

Выход примера программы равен

50 10 20


Вы также можете использовать ключевое слово this для вызова конструктора из другого конструктора

class sample
{
    public int x;

    public sample(int value) 
    {
        x = value;
    }

    public sample(sample obj) : this(obj.x) 
    {
    }
}

class run
{
    public static void Main(string[] args) 
    {
        sample s = new sample(20);
        sample ss = new sample(s);

        System.Console.WriteLine(ss.x);
    }
}

Вывод этого пример программы это

20

0 голосов
/ 10 октября 2018

Цепочка конструктора Т.е. вы можете использовать "Base" для отношения Is и "This" вы можете использовать для одного класса, когда вы хотите вызвать несколько Constructor в одном вызове.

  class BaseClass
{
    public BaseClass():this(10)
    {
    }
    public BaseClass(int val)
    {
    }
}
    class Program
    {
        static void Main(string[] args)
        {
            new BaseClass();
            ReadLine();
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...