2015-11-14 3 views
0

Я разрабатываю программу, которая активно использует делегатов. Для простоты предположим, что у меня есть следующий класс:Как ссылаться на делегат C# из своего кодового блока?

class ProcContainer<T> 
{ 
    public delegate T Proc(ProcContainer<T> parentContainer); // my delegate type 

    public Proc Content; // a field in the class in which a Proc "instance" is stored 
} 

Выражаясь словами: Proc является типом делегата, который принимает ProcContainer как ее (только) аргумент. И ProcContainer содержит Proc «экземпляр» в своем поле Content.

Теперь я хочу, чтобы создать делегат, как это:

T someVal = new T(); 

ProcContainer<T>.Proc proc = delegate(ProcContainer<T> parentContainer) 
{ 
    parentContainer.Content = <<<this_delegate>>>; 
    return someVal; 
}; 

Опять же, выражаясь словами: Я хотел бы создать экземпляр Proc приняв ProcContainer, который устанавливает содержание ProcContainer к Proc под рукой.

Поэтому, если вызывается мой Proc, он должен сам переписать текущее содержимое предоставленного ProcContainer.

Вопросы: Могу ли я сделать это на C#? Если да: как?

+2

объявить 'ProcContainer .Proc proc = null'; перед назначением его реальным кодом ... 'ProcContainer .Proc proc = null; proc = delegate (......) ' – Eser

ответ

1

<<<this_delegate>>> равен proc, но вам нужно немного изменить код, чтобы его можно было скомпилировать (и работать логически).

ProcContainer<T>.Proc proc = null; 
proc = delegate(ProcContainer<T> parentContainer) 
{ 
    parentContainer.Content = proc; 
    return someVal; 
}; 
+0

Большое спасибо.На самом деле, я хотел попробовать именно это, но, в конце концов, я этого не сделал, потому что, хотя этот «null» был заключен в скрытый класс помощника делегата вместо фактического экземпляра «Proc». Должен был попробовать все же. Хех. –

1

Отметьте, что у вас есть решение, но не объяснение причин, по которым исходный код вызывает ошибку. Трудно кратко сделать анонимную функцию, которая называет себя.

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

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

Теперь, вы можете разумно заметить, что в первом случае переменная обычно просто «упоминается» и фактически не «читается». А во втором случае «это» снова не разыменовывается. Вместо того, чтобы создавать специальное правило, которое смягчает общие правила, если нарушение появляется в неинвинированной анонимной функции, команда разработчиков языка решила просто применить правила в целом. Хотя это немного раздражает, нет специального случая, который должен быть спроектирован, указан, реализован, протестирован, а затем объяснен в документации.

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

Смежные вопросы