Конструктор с цепочкой "это" - PullRequest
3 голосов
/ 25 марта 2009

Почему первый конструктор в ClassA приводит к тому, что ошибка компилятора 'не может использовать "this" в intializer члена?

... или как мне заставить это работать?

Спасибо

public sealed class ClassA : IMethodA
{
    private readonly IMethodA _methodA;

    public ClassA():this(this)
    {}

    public ClassA(IMethodA methodA)
    {
        _methodA = methodA;
    }

    public void Run(int i)
    {
        _methodA.MethodA(i);
    }

    public void MethodA(int i)
    {
        Console.WriteLine(i.ToString());
    }
}

public interface IMethodA
{
    void MethodA(int i);
}

Ответы [ 4 ]

9 голосов
/ 25 марта 2009

Вам разрешено использовать синтаксис this(...) для вызова другого конструктора на том же уровне - однако вы не можете использовать this (текущий экземпляр) в этом контексте.

Самым простым вариантом здесь является дублирование кода назначения (_methodA = methodA).

Другим вариантом может быть объединение нулей:

public ClassA():this(null)
{}

public ClassA(IMethodA methodA) 
{ // defaults to "this" if null
    _methodA = methodA ?? this;
}
3 голосов
/ 25 марта 2009

Вы пытаетесь передать объект, прежде чем он будет построен. Хотя компилятор может сделать что-то разумное в этом случае, в общем, это не сработает.

Ваш реальный пример сработает, если вы просто сделаете это:

   public ClassA()
  {
    _methodA = this; 
  }

Но вы, вероятно, хотите поделиться большей логикой, поэтому просто используйте функцию.

  public ClassA()
  {
    SetStuff(); 
    _methodA = this; 
  }

  public ClassA(IMethodA methodA)
  {
    SetStuff(); 
    _methodA = methodA;
  }
3 голосов
/ 25 марта 2009

Это вызывается в разделе 10.11.1 спецификации C #

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

Нет способа заставить это работать с конструктором экземпляра, потому что к нему нельзя получить доступ. Что вы можете сделать, это сделать конструктор закрытым, создать метод инициализации и статический конструктор.

public sealed class ClassA : IMethodA {    
  private ClassA() { }
  private void Initialize(IMethodA param) { ... }
  public static ClassA Create() {
    var v1 = new ClassA();
    v1.Initialize(v1);
    return v1;
  }
  public static ClassA Create(IMethodA param) {
    var v1 = new ClassA();
    v1.Initialize(param);
    return v1;
  }
}
1 голос
/ 25 марта 2009

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

Я рекомендую просто использовать независимые конструкторы как таковые:

public sealed class ClassA : IMethodA
{
    private readonly IMethodA _methodA;

    public ClassA()
    {
        _methodA = this;
    }

    public ClassA(IMethodA methodA)
    {
        _methodA = methodA;
    }
}

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

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