How come Task implements IAsyncResult, but does not contain the AsyncWaitHandle member?
Asked Answered
W

2

5

Maybe it is a silly question.

The Task class is declared this way:

public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable

The IAsyncResult interface is declared like this:

public interface IAsyncResult
{
    object AsyncState { get; }
    WaitHandle AsyncWaitHandle { get; }
    bool CompletedSynchronously { get; }
    bool IsCompleted { get; }
}

But the member AsyncWaitHandle does not exist in the Task class or instances.

This code:

System.Threading.Tasks.Task t = new System.Threading.Tasks.Task(() => { }); 
t.AsyncWaitHandle.ToString(); 

Raises this compilation error:

Error 1 'System.Threading.Tasks.Task' does not contain a definition for 'AsyncWaitHandle' and no extension method 'AsyncWaitHandle' accepting a first argument of type 'System.Threading.Tasks.Task' could be found (are you missing a using directive or an assembly reference?)

However, this not only compiles:

System.IAsyncResult t = new System.Threading.Tasks.Task(() => { }); 
t.AsyncWaitHandle.ToString(); 

But also works, since the member exists. What is this sorcery?

It is a compiler trick or is it being hidden in another way?

Cheers.

Wolfhound answered 4/3, 2014 at 14:9 Comment(0)
W
6

Task implements IAsyncResult explicitly, so you have to cast first:

System.Threading.Tasks.Task t = new System.Threading.Tasks.Task(() => { }); 
((IAsyncResult)t).AsyncWaitHandle.ToString()

Explicit implementations are defined like:

public class Task : IAsyncResult
{
    WaitHandle IAsyncResult.AsyncWaitHandle
    {
        get { ... }
    }
}
Weekend answered 4/3, 2014 at 14:11 Comment(1)
So that is why I do not see it in Visual Studio through its metadata, because explicit implementations are not public. I didn't think on that. Thanks.Wolfhound
S
2

The msdn docs sum it up quite nicely.

http://msdn.microsoft.com/en-us/library/ms173157.aspx

The class member IControl.Paint is only available through the IControl interface, and ISurface.Paint is only available through ISurface. Both method implementations are separate, and neither is available directly on the class.

interface IControl
{
    void Paint();
}
interface ISurface
{
    void Paint();
}
class SampleClass : IControl, ISurface
{
    void IControl.Paint()
    {
        System.Console.WriteLine("IControl.Paint");
    }
    void ISurface.Paint()
    {
        System.Console.WriteLine("ISurface.Paint");
    }
}

The takeaway here is that explicit interface implementations are private and bound with compiler magic.

Sande answered 4/3, 2014 at 14:16 Comment(3)
It looks like a terrible thing to do. Isn't this a bend on the LSP?Wolfhound
@Wolfhound depending on your consideration of interfaces, its a straight up violation. However, interfaces are not abstract types. They are simply contracts that state you may safety cast to the interface 'type'. I'm not a fan either but it is consistent.Sande
@Wolfhound I'm more concerned that you would even do this - it is a concrete SRP violation.Sande

© 2022 - 2024 — McMap. All rights reserved.