Есть ли способ встроить функцию в делегат Action и одновременно ссылаться на нее?
-
20-08-2019 - |
Вопрос
Есть ли способ встроить делегированную задачу вместо разделения ее на другую функцию?
Исходный код:
private void ofdAttachment_FileOk(object sender, CancelEventArgs e)
{
System.Threading.ThreadPool.QueueUserWorkItem((o) => Attach());
}
void Attach() // I want to inline this function on FileOk event
{
if (this.InvokeRequired)
{
this.Invoke(new Action(Attach));
}
else
{
// attaching routine here
}
}
Я хотел, чтобы было так (не нужно создавать отдельную функцию):
private void ofdAttachment_FileOk(object sender, CancelEventArgs e)
{
Action attach = delegate
{
if (this.InvokeRequired)
{
// but it has compilation here
// "Use of unassigned local variable 'attach'"
this.Invoke(new Action(attach));
}
else
{
// attaching routine here
}
};
System.Threading.ThreadPool.QueueUserWorkItem((o) => attach());
}
Решение
Я думаю, это сработает:
private void ofdAttachment_FileOk(object sender, CancelEventArgs e)
{
Action attach = null;
attach = delegate
{
if (this.InvokeRequired)
{
// since we assigned null, we'll be ok, and the automatic
// closure generated by the compiler will make sure the value is here when
// we need it.
this.Invoke(new Action(attach));
}
else
{
// attaching routine here
}
};
System.Threading.ThreadPool.QueueUserWorkItem((o) => attach());
}
Все, что вам нужно сделать, это присвоить значение «attach» (нуль работает) перед строкой, объявляющей анонимный метод.Хотя я думаю, что первое немного легче понять.
Другие советы
Причина, по которой вы получаете ошибку «использование неназначенной переменной», заключается в том, как компилятор фактически генерирует код.Когда вы используете синтаксис делегата {}, компилятор создает для вас настоящий метод.Поскольку вы ссылаетесь на прикрепленное поле в своем делегате, компилятор пытается передать локальную переменную attach
к сгенерированному методу делегата.
Вот примерно переведенный код, который должен помочь сделать его более понятным:
private void ofdAttachment_FileOk(object sender, CancelEventArgs e)
{
Action attach = _b<>_1( attach );
System.Threading.ThreadPool.QueueUserWorkItem((o) => attach());
}
private Action _b<>_1( Action attach )
{
if (this.InvokeRequired)
{
// but it has compilation here
// "Use of unassigned local variable 'attach'"
this.Invoke(new Action(attach));
}
else
{
// attaching routine here
}
}
Обратите внимание, что поле Attach передается методу _b<>_1 перед его инициализацией.