在运行时能否判断一个对象是否可等待?

12

最近了解到,任何具有返回awaiterGetAwaiter方法的对象都可以进行await操作。即使它是一个扩展方法,这意味着基本上任何对象都可以被选择为可await对象。

但是有没有一种方法在运行时判断一个对象是否可以进行await操作?普通的反射无法起作用,因为它不会列出对象的扩展方法。

我提出这个问题并没有特定的需求,只是好奇是否可能。


1
不行,因为这两种方法都使用编译器完成的鸭子类型。即使可以,你会用那些信息做什么呢? - D Stanley
你能否简单地解释为什么不能使用反射查找扩展方法?我能够理解它们为什么不容易获得,但我不明白为什么不能搜索它们。 - 31eee384
1
@31eee384 可用扩展的集合取决于源代码中使用的语句或在加载时存在的程序集集合。 - usr
@31eee384 哦,相反的情况 :) 你需要usings、当前命名空间、目标成员和编译时引用。 - usr
@usr 我一定表达有误,因为这对我来说没有意义——这是我设想的:在运行时,您可以查看所有已加载的程序集,以查找符合条件的方法和扩展方法。这将告诉您它是否可以是可等待的,但这并不意味着它在源文件中可等待的,因为新程序集可能已添加扩展方法。这有意义吗? - 31eee384
显示剩余4条评论
1个回答

7

这是不可能的,因为C#编译器用于作出该决定的信息已经消失了。

为了解决扩展方法,我们需要知道已导入的命名空间。该信息在运行时不可用。这是一个仅限于C#的概念。CLR不知道using是什么。

我无法想出任何理由来确定对象在运行时是否可能等待,因为您无法根据那个信息采取行动。也许您可以检查对象是否为Task


根据这个答案,在运行时确定扩展方法是可能的,这将使得这种推理是不正确的。 - BlueRaja - Danny Pflughoeft
@BlueRaja-DannyPflughoeft 你必须查看所有可能定义扩展方法的程序集。这是不可能的,因为您无法知道在编译时引用了哪些程序集,但可能未使用和丢弃。此外,您不知道所采用的用法。还有,可能存在在任何地方都没有引用但确实存在的程序集中定义的扩展。 - usr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接