Если у Вас уже есть другие вызовы к Windows API, нет никакого вреда в использовании решения Peters. Но я понимаю Ваше беспокойство об этом и склонялся бы к аналогичному решению как Ваши, использующий только технические возможности Платформы. В конце концов, различие в производительности (если существует один) не должно быть значительным.
я проявил бы не рекурсивный подход:
public static Control FindFocusedControl(Control control)
{
var container = control as IContainerControl;
while (container != null)
{
control = container.ActiveControl;
container = control as IContainerControl;
}
return control;
}
Вы можете использовать лямбда-выражение блока операторов:
Action<int> action = x =>
{
switch(x)
{
case 0: Console.WriteLine("0"); break;
default: Console.WriteLine("Not 0"); break;
}
};
Но вы не можете сделать это в «лямбда-выражении с одним выражением», поэтому это недопустимо:
// This won't work
Expression<Func<int, int>> action = x =>
switch(x)
{
case 0: return 0;
default: return x + 1;
};
Это означает, что вы не можете используйте переключатель в дереве выражений (по крайней мере, сгенерированный компилятором C #; я считаю, что .NET 4.0 по крайней мере поддерживает его в библиотеках).
В чистом выражении
(в .NET 3.5) самое близкое, что вы можете получить, - это составное условное выражение:
Expression<Func<int, string>> func = x =>
x == 1 ? "abc" : (
x == 2 ? "def" : (
x == 3 ? "ghi" :
"jkl")); /// yes, this is ugly as sin...
Не весело, особенно когда оно становится сложным. Если вы имеете в виду lamda-выражение с телом оператора (только для использования с LINQ-to-Objects), тогда все внутри фигурных скобок допустимо:
Func<int, string> func = x => {
switch (x){
case 1: return "abc";
case 2: return "def";
case 3: return "ghi";
default: return "jkl";
}
};
Конечно, вы можете передать работу на аутсорсинг; например, LINQ-to-SQL позволяет сопоставить скалярную UDF (в базе данных) с методом в контексте данных (который фактически не используется) - например:
var qry = from cust in ctx.Customers
select new {cust.Name, CustomerType = ctx.MapType(cust.TypeFlag) };
где MapType
- это UDF, которая выполняет работу на сервере базы данных.
Да, это работает, но вы должны поместить свой код в блок. Пример:
private bool DoSomething(Func<string, bool> callback)
{
return callback("FOO");
}
Затем, чтобы вызвать его:
DoSomething(val =>
{
switch (val)
{
case "Foo":
return true;
default:
return false;
}
});
Хм, я не вижу причин, почему это не должно работать. Просто будьте осторожны с синтаксисом, который вы используете
param => {
// Nearly any code!
}
delegate (param) {
// Nearly any code!
}
param => JustASingleExpression (No switches)
Я тоже это проверил: -)
[Test]
public void SwitchInLambda()
{
TakeALambda(i => {
switch (i)
{
case 2:
return "Smurf";
default:
return "Gnurf";
}
});
}
public void TakeALambda(Func<int, string> func)
{
System.Diagnostics.Debug.WriteLine(func(2));
}
Работает нормально (выводит "Smurf")!