【问题标题】:How come Task implements IAsyncResult, but does not contain the AsyncWaitHandle member?为什么Task实现了IAsyncResult,却不包含AsyncWaitHandle成员?
【发布时间】:2014-03-04 14:09:04
【问题描述】:

也许这是一个愚蠢的问题。

Task 类是这样声明的:

public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable

IAsyncResult 接口声明如下:

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

AsyncWaitHandle 成员在Task 类或实例中不存在。

这段代码:

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

引发此编译错误:

错误 1 ​​'System.Threading.Tasks.Task' 不包含定义 对于 'AsyncWaitHandle' 并且没有扩展方法 'AsyncWaitHandle' 接受“System.Threading.Tasks.Task”类型的第一个参数可以 被发现(您是否缺少 using 指令或程序集引用?)

但是,这不仅编译:

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

但也有效,因为该成员存在。这是什么法术?

这是一个编译器技巧还是以其他方式隐藏?

干杯。

【问题讨论】:

    标签: c# oop interface task iasyncresult


    【解决方案1】:

    Task 明确实现了IAsyncResult,所以你必须先转换:

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

    显式实现定义如下:

    public class Task : IAsyncResult
    {
        WaitHandle IAsyncResult.AsyncWaitHandle
        {
            get { ... }
        }
    }
    

    【讨论】:

    • 这就是为什么我没有通过它的元数据在 Visual Studio 中看到它,因为显式实现不是公开的。我没有想到这一点。谢谢。
    【解决方案2】:

    msdn 文档总结得很好。

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

    类成员 IControl.Paint 只能通过 IControl 接口,而 ISurface.Paint 只能通过 ISurface 使用。两个都 方法实现是独立的,并且都不能直接使用 在课堂上。

    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");
        }
    }
    

    这里的要点是显式接口实现是私有的并且与编译器魔法绑定。

    【讨论】:

    • 这看起来是一件很糟糕的事情。这不是 LSP 的弯路吗?
    • @vtortola 取决于您对接口的考虑,这是一个直接的违规行为。但是,接口不是抽象类型。它们只是声明您可以安全地转换为接口“类型”的合同。我也不是粉丝,但它是一致的。
    • @vtortola 我更担心你会这样做 - 这是一个具体的 SRP 违规。
    猜你喜欢
    • 2013-01-06
    • 2014-08-16
    • 2013-03-25
    • 2019-11-09
    • 1970-01-01
    • 2012-04-22
    • 1970-01-01
    • 2016-07-24
    • 1970-01-01
    相关资源
    最近更新 更多