我想传递一个返回void并接受param int的方法。我怎么做?
有人可以告诉我非lambda和lambda版本吗?
private void LongTask(int s)
{
Thread.Sleep(s* 1000);
}
public void Run()
{
Task q = Task.Run(Action<int>(LongTask));
}
在您的示例中,您没有显示要传递给该方法的值。很难确定您要问的是什么。但是我想您正在要求说明如何调用您的方法LongTask()
,为Task.Run()
操作传递适当的值,并同时使用lambda语法和非lambda语法提供此说明。
注意:实际上,这几乎是特定于的Task.Run()
。这在您将委托传递给方法的任何时候都适用,其中委托需要代表一种方法,该方法的签名与所调用方法所使用的签名不同。这Task.Run()
是参与这里几乎是偶然的。
反正…
实际上,由于lambda表达式(在此用法中)可编译为匿名方法,因此实际上有三个选择:
“老派”匿名方法:
public void Run()
{
int someValue = 17;
Task q = Task.Run(delegate { LongTask(someValue); });
}
上面的代码使编译器创建一个匿名方法(delegate() { LongTask(someValue); }
),并生成代码以创建传递给该Task.Run()
方法的委托实例。委托的类型是从用法中推断出来的(即基于与匿名方法声明匹配的一种方法重载)。
Lambda匿名方法:
public void Run()
{
int someValue = 17;
Task q = Task.Run(() => LongTask(someValue));
}
除了使用名义上更简洁的lambda语法声明匿名方法外,以上内容与前面的示例相同。我说“名义上”是因为在这种特殊情况下,它实际上并没有那么短。但是在其他情况下,lambda语法更方便。通常,当匿名方法返回值时,由于使用lambda语法,该return
语句是隐式的。
显式:
class A
{
private readonly int _value;
private readonly Action<int> _action;
public A(int value, Action<int> action)
{
_value = value;
_action = action;
}
public void M() { _action(_value); }
}
public void Run()
{
int someValue = 17;
Task q = Task.Run((Action)(new A(someValue, LongTask).M));
}
上面的内容依赖于显式编写的类,其作用与匿名方法选项导致的编译器生成的类的目的相同。根据确切的情况,编译器生成的类在实现上可能会有很大不同。但是其行为本质上是相同的:创建了一个类的实例,在其中存储了所需的值,并且在类中包含了具有适当签名的方法,该方法的主体是您要执行的代码。
(此外:在这种情况下,为简洁起见,我展示了一个实际上使用委托实例的实现,而不是对目标对象和方法调用进行硬编码。实际上,这是比编译器实际生成的可重用的实现,主要是因为编译器必须处理许多更复杂的场景,并且此优化仅在非常狭窄的场景中才有用,即只有一种方法被调用,编译器还将存储this
并复制匿名主体方法到生成的方法,方法是使用存储的this
引用和所需的任何其他捕获的变量(例如,调用该LongTask()
方法。)
在上面的变量_value
是readonly
,但是在匿名方法中,它们通常是从匿名方法的上下文中捕获的可变变量。为了更好地模拟匿名方法通常如何工作,您需要更多类似这样的东西:
class A
{
public int value;
private readonly Action<int> _action;
public A(int value, Action<int> action)
{
this.value = value;
_action = action;
}
public void M() { _action(value); }
}
public void Run()
{
A a = new A(17, LongTask);
Task q = Task.Run((Action)a.M);
a.value = 19;
}
请注意,以上value
是公共字段。并且代码实际上在调用后修改了变量Task.Run()
。这类似于更改someValue
匿名方法示例中的值(同样,在调用之后Task.Run()
),并且具有相同的风险:如果Task.Run()
在任务可以执行方法调用之前执行了方法之后的赋值,那么您将传递不同的值如果任务可以先执行该方法,则返回该方法。
道德:始终当心捕获的变量,并确保它们具有预期的寿命和价值。
顺便说一句,Action
在最后两个示例中,需要强制转换为所需的委托类型,因为否则Task.Run()
,选择的重载在Task.Run(Action)
和之间对编译器是不明确的Task.Run(Func<Task>)
。简短版本:尝试从方法组转换为委托类型并将其与特定的重载匹配时,将忽略委托签名的返回类型。有关较长版本,请参见编译器歧义调用错误-匿名方法和带有Func <>或Action的方法组。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句