我有一个长期运行的任务,在不相关的类中具有相同的名称。我试图使用动态的通用方法编写此代码。我收到以下错误
用户代码未处理Microsoft.CSharp.RuntimeBinder.RuntimeBinderException Message =无法将类型'void'隐式转换为'object'
我试图将代码隔离到以下内容
class Program
{
static void Main(string[] args)
{
MainAsync();
Console.ReadKey();
}
static async void MainAsync()
{
var classA = new ClassA();
var classB = new ClassB();
await RunTask1(classA);
await RunTask1(classB);
await RunTask(classA);
await RunTask(classB);
}
static async Task RunTask(dynamic val)
{
await Task.Run(() => val.CommonLongRunningTask());
}
static async Task RunTask1(ClassA val)
{
await Task.Run(() => val.CommonLongRunningTask());
}
static async Task RunTask1(ClassB val)
{
await Task.Run(() => val.CommonLongRunningTask());
}
}
internal class ClassA
{
public void CommonLongRunningTask()
{
Console.WriteLine("Class A CommonLongRunningTask");
}
}
internal class ClassB
{
public void CommonLongRunningTask()
{
Console.WriteLine("Class B CommonLongRunningTask");
}
}
如果我通过对象本身(RunTask1)而不是动态对象,它将起作用。我试图了解动态传递时发生的情况。
我还无法将其追溯到该语言中的某些内容,但是看来您无法使用带有动态表达式的表达式lambda。 更新:无论是否存在void方法调用,涉及a的表达式dynamic
始终为类型dynamic
,请参见语言方面更新
声明lambda起作用:
private static async Task RunTask(dynamic val)
{
await Task.Run(() =>
{
val.CommonLongRunningTask();
});
}
实际上,这里发生的是编译器遇到此情况时:
() => val.CommonLongRunningTask()
它解释为等同于:
() => {return val.CommonLongRunningTask();}
...因为在编译时它不知道您调用的任何内容val
都不会返回任何内容。在运行时,它遇到val.CommonLongRunningTask()
类型为表达式的表达式,void
但是return
即使对于最低的公分母也不能达到该值object
,因此抛出异常并显示消息Cannot implicitly convert type 'void' to 'object'
如果重新编写RunTask
如下代码,则您将有一个完全相同的例外:
private static async Task RunTask(dynamic val)
{
await Task.Run(() =>
{
return val.CommonLongRunningTask();
});
}
经过更多的研究/讨论,C#规范的7.5.2节详细说明了为什么会发生这种情况。本质上,任何涉及动态的东西本身就是动态类型(因为在编译时编译器无法知道事物将如何绑定),因此将“ val.CommonLongRunningTask()”视为返回动态的东西(因此会出现运行时错误)当它意识到在运行时是无效的时)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句