У «Большого масштаба C ++ Software Design» Джона Лакоса были инструменты, которые извлекали зависимости времени компиляции среди исходных файлов.
К сожалению, их хранилище на сайте Аддисона-Уэсли пропало (вместе с самим сайтом AW), но я нашел тарбол здесь: http://prdownloads.sourceforge.net/introspector/LSC-rpkg-0.1. tgz? download
Я нашел это полезным несколько работ назад, и он достоин того, чтобы быть свободным.
Кстати, если вы еще не читали книгу Лакоса, похоже, ваш проект принесет пользу. (Текущее издание немного устарело, но я слышал, что у Лакоса есть другая книга, выходящая в 2012 году.)
Да. В .NET 3.5 вы можете использовать делегаты Func и Action . Делегаты Func возвращают значение, а делегаты Action возвращают void. Вот как будут выглядеть имена типов:
System.Func<TReturn> // (no arg, with return value)
System.Func<T, TReturn> // (1 arg, with return value)
System.Func<T1, T2, TReturn> // (2 arg, with return value)
System.Func<T1, T2, T3, TReturn> // (3 arg, with return value)
System.Func<T1, T2, T3, T4, TReturn> // (4 arg, with return value)
System.Action // (no arg, no return value)
System.Action<T> // (1 arg, no return value)
System.Action<T1, T2> // (2 arg, no return value)
System.Action<T1, T2, T3> // (3 arg, no return value)
System.Action<T1, T2, T3, T4> // (4 arg, no return value)
Я не знаю, почему они остановились на 4 аргументах каждое, но для меня этого всегда было достаточно.
Вот делегат Action, который вы можете использовать, например:
private void RefreshForm()
{
if (InvokeRequired) Invoke(new Action(Refresh));
else Refresh();
}
Или с лямбда-синтаксисом:
private void RefreshForm()
{
if (InvokeRequired) Invoke((Action)(() => Refresh()));
else Refresh();
}
Наконец, есть синтаксис анонимного делегата:
private void RefreshForm()
{
if (InvokeRequired) Invoke((Action)(delegate { Refresh(); }));
else Refresh();
}
В этом конкретном случае вы можете (и должны) просто использовать MethodInvoker для этого ... вот почему он существует.
if (InvokeRequired)
Invoke(new MethodInvoker(Refresh));
else
Refresh();
Если бы вы делали что-то еще, вы могли бы, как ответили другие, использовать Func
Short version:
Invoke((MethodInvoker)delegate { Refresh(); });
Then you can also drop the check of InvokeRequired; you can just call it as it is. Works also if you need to pass parameters, so there is no need for other parameter-specific delegates (works just as well with the parameter-less Action delegate as well):
private void SetControlText(Control ctl, string text)
{
Invoke((MethodInvoker)delegate { ctl.Text = text; });
}
Мне действительно нужен весь делегат специально для этого? не там какие-либо общие делегаты?
Определение ваших собственных делегатов действительно может облегчить отладку, хотя бы потому, что Intellisense может сообщить вам имена ваших параметров. Например, вы пишете делегат следующим образом:
public delegate int UpdateDelegate(int userID, string city, string, state, string zip);
Когда вы используете его код, .NET сообщит вам имена параметров, имя делегата и т. Д., Так что в определении делегата много контекста, если вы не точно знаете, как что-то используется.
Однако, если вы не возражаете пожертвовать Intellisense, уже существует класс делегатов, определенный в пространстве имен System, который может использоваться как специальные делегаты:
Func<T>
Func<T, U>
Func<T, U, V>
Func<T, U, V, W>
Action, Action<T>
Action<T, U>
Action<T, U, V>
Action<T, U, V, W>
Только Действие
и Действие
существует в .NET 2.0, но его достаточно просто объявить вспомогательный класс с остальными делегатами, которые вам нужны для такого рода различных специальных функций.
Да, есть универсальные делегаты. Action
- это универсальный делегат, который принимает некоторые параметры и не возвращает значения, а Func
- универсальный делегат, который принимает некоторые параметры и возвращает значение.