我正在尝试将参数传递给函数,该参数是匿名委托(没有输入参数,没有返回值)。
这样的事情:
private function DoSomething(delegate cmd)
{
cmd();
}
然后,我想用这个函数以这种方式调用函数:
DoSomething(delegate
{
Console.WriteLine("Hooah!");
});
我想要这种特定的方式,因为它易于使用的写作风格。
可能的?
答案 0 :(得分:22)
正是出于这样的目的,Microsoft在.NET框架中创建了Action和Func包装类。这两个课程都依赖于anonymous functions。如果您不需要返回任何结果,只需执行匿名函数,请使用Action:
private void DoSomething(Action action)
{
action();
}
可以像这样使用:
DoSomething(() =>
{
Console.WriteLine("test");
});
() =>
字词是lambda expression,意思是input with no parameters is calling ...
。有关详细说明,请参阅文档。
如果要返回结果,请使用Func委托:
private T DoSomething<T>(Func<T> actionWithResult)
{
return actionWithResult();
}
用法:
Console.WriteLine(DoSomething<int>(() =>
{
return 100;
}));
两个包装器都有覆盖,最多可接受8个参数。
使用Func时,最后一个参数始终是返回类型:
// returns a string
Func<string> t = () => { return "test string"; };
// first parameter is of type int, result of type string
Func<int, string> toString = (id) => { return id.ToString(); };
// parameters are of type int and float, result is string
Func<int, float, string> sumToString = (n1, n2) => { return (n1 + n2).ToString(); };
Func包装器可以直接用于类型参数:
Func<string, string> up = text => text.ToUpper();
Console.WriteLine(up("test"));
我经常使用Func来创建一个包含在try / catch块中的通用执行程序,并记录是否发生了某些事情。这样我减少了重复代码:
private T safeCallWithLog<T>(Func<T> action)
{
try
{
return action();
}
catch (Exception ex)
{
Console.WriteLine(String.Format("Oops ...: {0}", ex.Message));
}
// return default type if an error occured
return default(T);
}
用法:
var result = safeCallWithLog<DbEntry>(() =>
{
return databaseContext.GetEntryWithId(42);
});
var id = safeCallWithLog<int>(() =>
{
return databaseContext.GetIdFor("J.D.");
});
您仍然可以使用原始delegate concept。 Action和Func类只是predefined generic delegate methods的包装。
// declare delegate contract
private delegate void output();
// create caller method
private void method(output fun)
{
fun();
}
// some test functions, that must match exactly the delegate description
// return type and number of arguments
private void test1()
{
Console.WriteLine("1");
}
private void test2()
{
Console.WriteLine(DateTime.Now.ToString());
}
// call different methods
method(test1);
method(test2);
// inline call without hard coded method
method(delegate()
{
Console.WriteLine("inline");
});
答案 1 :(得分:3)
.NET内置了很多这些内容。Action
是你想要的没有参数和没有返回类型的那个:
private function DoSomething(Action cmd)
{
cmd();
}
如果你想要一个带参数但没有返回类型的委托(例如Action<int, int>
表示一个带有两个整数且没有返回的方法),那么还有一个Action的通用版本。
Func
和Predicate
(以及那些的通用版本)也存在。
答案 2 :(得分:0)
当然有可能。对于没有返回类型的方法,请使用Action
,否则使用Func<>
。
public void Function(Action action)
{
action();
}
并将其称为
Function(() => System.Console.WriteLine("test"));
使用lambdas而不是delegate
关键字更令人愉快。您甚至可以使用action.Invoke()
执行操作,但在我看来,最好将其称为实际上是一种方法。
答案 3 :(得分:0)
然而,Pasty描述了大多数可能的解决方案,我只想添加关键词delegate。
在示例中,它用于描述输入参数
private function DoSomething(delegate cmd)
{
cmd();
}
但它可用于声明用于包含指向函数的指针的对象类型:
public delegate *returnParameterType* NewTypeName(*inputParamType1* inputParam1, ...)
然后使用 NewTypeName 作为输入参数的类型:
private function DoSomething(NewTypeName cmd)
{
cmd();
}
第二个使用关键字&#39;委托&#39;就像你的例子 - 声明匿名方法
委托() { Console.WriteLine(&#34;呼啊&#34;!); }
但是在这种情况下,必须将这样的方法分配给合适的定义委托,或者像Action那样使用泛型委托,因为Action不应该有输出参数
private void delegate Output();
Output func = delegate(){Console.WriteLine("Hooah!");}
或
Action func1 = delegate(){Console.WriteLine("Hooah!");}