TcpClient.Dispose() 方法会关闭 TcpClient.GetStream() 吗?

5
关闭TcpClient时需要关闭流。通常的做法是:
        client.GetStream().Close();
        client.Close();

因此,仅使用client.Close()是不够的。我的问题是client.Dispose()是否与client.GetStream().Close()相同,以便关闭如下:

        client.Dispose();
        client.Close();

我从阅读TcpClient参考源代码中理解到Dispose方法关闭流,那么我是正确的还是有遗漏?非常感谢。


1
你为什么认为只有 Close() 不够?在我看来应该没问题。通常情况下,我不会显式地调用 Close()Dispose(),而是使用 using 语句。但只使用 Dispose() 应该就足够了。 - Jon Skeet
所以它的作用与 TcpClient.GetStream().Close 相同吗?请注意,Dispose 属于 TcpClient 而不是 NetworkStream - vkr02692
@JonSkeet Close() 只关闭流,从 MSDN 中的 Dispose 释放 TcpClient 使用的托管和非托管资源。 - BWA
1
从另一个角度来看,如果TcpClient没有清理底层流,我会认为它存在缺陷。依赖于消费者代码获取您的可处理内部并清理它们是一种灾难性的做法。 - James Thorpe
1
@Karol:但是在这里关闭和处理是等效的。关闭客户端应该会关闭套接字,这将释放资源... - Jon Skeet
显示剩余7条评论
2个回答

11

Close方法会调用Dispose方法,Dispose方法会释放流资源:

IDisposable dataStream = m_DataStream;
if (dataStream != null)
{
    dataStream.Dispose();
}

你不需要同时调用CloseDispose。选择其中一个即可。

你可以查看源代码

IDisposable类通常还有另一个方法,与Dispose相同,但具有不同的、特定于域的名称。很多时候,IDisposable.Dispose被显式实现,以便在使用语句或强制转换后使用,但不会使类接口混乱。


@vkr02692 是的,Close 就足够了。 - Jakub Lortz
3
我发现这个框架中的这种模式非常奇怪 - Close只是意味着“我想关闭流”,但Dispose意味着“我已经完成了对类实例的使用”。这些词不是同义词。Dispose通常用作实例的最后一条指令,但Close只是意味着“关闭流”。为什么Close()会调用Dispose()?(我知道它确实这样做,但这是一个有趣的混淆点)。 - PhillipH
@PhillipH 为什么你想要在不释放资源的情况下 Close 呢?这没有任何意义。 - vkr02692
@PhillipH 当存在“Open”方法时,我只会感到困惑。当然,我无法打开已经被Dispose的实例,但是关闭了呢?不确定。 - Jakub Lortz
TcpClient不是一个密封类。仅关闭其流并不意味着我已经完成了实例的生命周期。TcpClient的作者没有将Close设置为虚拟方法,因此继承者无法更改行为,而且该行为是具有破坏性的。作为该类继承版本的使用者,我不希望简单的“关闭流”命令调用Disposer,因为我没有告诉实例我已经完成了使用它的操作。继承者可能会有其他非流特性,我想在对象生命周期中使用它们。 - PhillipH
显示剩余4条评论

1
client.Dispose

或者

client.Close 

这两种方法都能实现同样的功能,只需要调用一次即可。

并且两种方法都会关闭网络流。

来自MSDN:

调用此方法最终将导致关闭相关的套接字,并且如果创建了用于发送和接收数据的相关NetworkStream,则也会关闭该流。


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