11

I recently learned that any object with a GetAwaiter method returning an awaiter can be await-ed. This is true even if it's an extension method, meaning basically any object can be made await-able, if you so choose.

But is there a way to tell at runtime if an object is await-able? Normal reflection won't work, since it doesn't list an object's extension methods.

I don't have a particular need in mind when asking this question, I'm just curious if it's possible.

Community
  • 1
  • 1
BlueRaja - Danny Pflughoeft
  • 84,206
  • 33
  • 197
  • 283
  • 1
    No, because both methods use duck-typing which is done by the compiler. Even if you could, what would you _do_ with that information? – D Stanley Sep 01 '15 at 21:42
  • Is there a straightforward reason you can't look for extension methods with reflection? I can see why they aren't readily available, but I don't see a reason you can't search for them. – 31eee384 Sep 01 '15 at 21:52
  • 1
    @31eee384 the set of available extensions depends on the using statements in the source code or on the set of assemblies that happen to be loaded at the time. – usr Sep 01 '15 at 21:54
  • @usr Hmm, so basically it's impossible to tell if an object was awaitable in the source, but you could find out if it's awaitable with the current set of loaded assemblies? Got it. – 31eee384 Sep 01 '15 at 22:01
  • @31eee384 uh the opposite :) You need the usings, the current namespace, target members and compile-time references. – usr Sep 01 '15 at 22:04
  • @usr I must have phrased that wrong, because that doesn't make sense to me--here's what I envision: during runtime, you could look through all loaded assemblies to find methods and extension methods that match the criteria. This will tell if you if it could have been awaitable, but it doesn't mean that it *was* awaitable in the source file, since a new assembly may have added an extension method. Does that make sense? – 31eee384 Sep 01 '15 at 22:09
  • @31eee384 this check would have false positives and false negatives. A critical assembly might not have been loaded at that time. It's non-deterministic what assemblies are loaded. – usr Sep 01 '15 at 22:10
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/88518/discussion-between-31eee384-and-usr). – 31eee384 Sep 01 '15 at 22:11
  • It's perfectly possible to have two or more extension methods available from loaded assemblies, with the same name, and which can be used with the object in question, but either only one available in the source because of `using`s or where one is the obvious overload to call based on the object's type, but the source used a cast to force the other to be called, and so on. – Jon Hanna Sep 01 '15 at 22:16

1 Answers1

7

It's not possible because the information that the C# compiler uses to make that decision is gone.

In order to resolve extension methods we need to know the namespaces that are imported. That information is not available at runtime. It is a C#-only concept. The CLR does not know what a using is.

I cannot think of any reason you would want to see if an object is possibly awaitable at runtime because you can't act on that information. Maybe you could check if the object is a Task instead?

usr
  • 168,620
  • 35
  • 240
  • 369
  • According to [this answer](http://stackoverflow.com/a/299526/238419), it's possible to determine extension methods at runtime, which would make this reasoning incorrect. – BlueRaja - Danny Pflughoeft Dec 03 '15 at 16:52
  • @BlueRaja-DannyPflughoeft `You have to look in all the assemblies where the extension method may be defined.` That is not possible because you can't know what assemblies were referenced at compile time but maybe went unused and discarded. Also, you don't know the usings that were in place. Also, there could be extensions defined in assemblies that were never referenced anywhere but that exist. – usr Dec 03 '15 at 16:59