2012-03-28 2 views
8

В коде ниже я должен объявить метод MdrResponseInterpreterstatic в противном случае у меня есть ошибка компиляции.Почему делегат должен быть статичным?

class.... { 

    private StandardBuilder _mdrResponseBuilder = 
     new StandardBuilder(MdrResponseInterpreter); 

    public static bool MdrResponseInterpreter(DNMessageDeliverer builder, 
               DNFieldSet message) 
    { 
     // .... work 
    } 

Почему? Как _mdrResponseBuilder не статична я ожидаю, что MdrResponseInterpreter должен быть в состоянии получить доступ к this

ответ

11

Поскольку поле Инициализаторы не имеют доступа к this членов/экземпляра. Переместите инициализацию в конструктор, если вы хотите получить доступ к членам экземпляра.

Спецификация говорит:

переменной инициализатор для поля экземпляра не может ссылаться на экземпляр создается. Таким образом, это ошибка во время компиляции ссылаться this в переменном инициализаторе

Хотя ваш код не явно ссылаться this, групповой метод делегирования преобразования делает ссылку this неявно, если метод является членом экземпляра.

1

Вам не разрешено использовать экземпляры-члены в инициализаторах.

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

+1

Там определенно * есть * объект в этой точке (в противном случае, где назначается значение?), Но вам еще не разрешен доступ к этому. –

+0

Конечно, я был неясен. Обновлен мой ответ. – Botz3000

+0

Я бы сказал, что это неясно. Объект * does * существует, полностью. Возможно, он не был полностью * инициализирован *, но это верно и в теле конструктора. (Могут быть другие производные тела конструкторов, которые еще не запущены, тоже ...) –

1

Метод должен быть статичным, поскольку он вызывается при инициализации объекта, прежде чем конструктор начнет выполнение. Если вы хотите получить доступ к this, вызовите метод инициализации внутри вашего конструктора.

5

Чтобы добавить ответ CodeInChaos (что правильно), вы можете просто переместить задание конструктору:

private StandartBuilder _mdrResponsBuilder; 

public Foo() // Whatever your type is called 
{ 
    // Simpler syntax for creating a delegate, too. Just use a 
    // method group conversion... 
    _mdrResponsBuilder = MdrResponseInterpreter; 
} 

EDIT: Выше предполагается, что StandartBuilder является типом делегата. Если это тип с конструктором , принимающий тип делегата, то вам нужно вернуться к new StandartBuilder(MdrResponseInterpreter), но все равно иметь его в конструкторе.

+0

@ Downvoter: Зачем прокомментировать? –

+0

Просто интересно, как это верно? _mdrResponsBuilder = MdrResponseInterpreter? Ничто в вопросе не указывает, что StandardBuilder является делегатом ... Это может быть класс, принимающий Func в своем конструкторе? Btw, я не уменьшил – odalet

+1

@odalet: Да, это возможно. Я думаю, что более вероятно (учитывая название вопроса), что это тип делегата. Будет редактировать, чтобы уточнить. –