Вызов одного конструктора из тела другого в C # - PullRequest
49 голосов
/ 28 сентября 2011

Мне нужно вызвать один конструктор из тела другого. Как я могу это сделать?

В основном

class foo {
    public foo (int x, int y)
    {
    }

    public foo (string s)
    {
        // ... do something

        // Call another constructor
        this (x, y); // Doesn't work
        foo (x, y); // neither
    }
}

Ответы [ 6 ]

69 голосов
/ 28 сентября 2011

Вы не можете.

Вам нужно будет найти способ связать конструкторы, как в:

public foo (int x, int y) { }
public foo (string s) : this(XFromString(s), YFromString(s)) { ... }

или переместить код построения в общий метод настройки,как это:

public foo (int x, int y) { Setup(x, y); }
public foo (string s)
{
   // do stuff
   int x = XFromString(s);
   int y = YFromString(s);
   Setup(x, y);
}

public void Setup(int x, int y) { ... }
35 голосов
/ 28 сентября 2011

this(x, y) правильно, но должно быть до начала тела конструктора:

public Foo(int x, int y)
{
    ...
}

public Foo(string s) : this(5, 10)
{
}

Обратите внимание, что:

  • Вы можете связать только один конструктор, либо this, либо base - этот конструктор, конечно, может соединиться с другим.
  • Тело конструктора выполняет после связанного вызова конструктора. Нет способа сначала выполнить тело конструктора.
  • Вы не можете использовать this в аргументах другого конструктора, включая вызов методов экземпляра, но вы можете вызывать статические методы.
  • Любые инициализаторы переменных экземпляра выполняются до связанного вызова.

У меня есть немного больше информации в моей статье о цепочке конструктора .

6 голосов
/ 28 сентября 2011

Чтобы явно вызывать и базовый конструктор, и этот конструктор класса, вам нужно использовать синтаксис, приведенный ниже (обратите внимание, что в C # вы не можете использовать его для инициализации полей, как в C ++):

class foo
{
    public foo (int x, int y)
    {
    }

    public foo (string s) : this(5, 6)
    {
        // ... do something
    }
}

// РЕДАКТИРОВАТЬ: заметил, что вы использовали x, y в вашем примере. Конечно, значения, данные при вызове ctor таким способом, не могут полагаться на параметры другого конструктора, они должны быть разрешены другим способом (они не обязательно должны быть константами, хотя, как в примере отредактированного кода выше). Если x и y вычислены из s, вы можете сделать это следующим образом:

public foo (string s) : this(GetX(s), GetY(s))
1 голос
/ 28 сентября 2011

Я столкнулся с этой проблемой раз или два сам ... В итоге мне пришлось извлечь любую логику, которая мне нужна в этом другом конструкторе, в метод private void и вызывать ее в обоих местах.

class foo
{
  private void Initialize(int x, int y)
  {
    //... do stuff
  }

  public foo(int x, int y)
  {
    Initialize(x, y);
  }

  public foo(string s_
  {
    // ... do stuff

    Initialize(x, y)
    // ... more stuff
  }
}
1 голос
/ 28 сентября 2011

Это не поддерживается - см. Конструкторы в C # .

Однако вы можете реализовать общий (приватный) метод, который вы вызываете из разных конструкторов ...

0 голосов
/ 20 сентября 2018

Есть примечание в описании из MethodBase.Invoke в MSDN

Если перегрузка этого метода используется для вызова конструктора экземпляра, объект, предоставленный для объекта obj, повторно инициализирован; то есть весь экземпляр инициализаторы выполнены. Возвращаемое значение равно нулю. Если класс вызывается конструктор, класс повторно инициализируется; то есть весь класс инициализаторы выполнены. Возвращаемое значение равно нулю.

т.е. Вы можете получить метод конструктора с помощью отражения и вызвать его через Invoke в теле вашего нового конструктора. Но я не пробовал . И, конечно, у этого решения есть много недостатков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...