我应该在C#中使用异常来增强基类兼容性吗?

我应该在C#中使用异常来增强基类兼容性吗?,c#,design-patterns,exception,C#,Design Patterns,Exception,一方面,我被告知C#中的异常是“昂贵的”,但另一方面,我被困在如何实现这一点上 我的问题是:我正在制作一个流派生,它包装了一个网络流。现在,我面临的问题是:Read(byte[]buffer,int offset,int count)。从函数的流文档: 返回: 。。。或者,如果已到达流的末尾,则为零(0) 问题是,在我实现的协议中,远程端可以发送“记录结束”令牌或“请响应”令牌。显然,如果这种情况发生在Read()的开头,这会导致问题,因为我需要从函数返回,而且我没有读取任何内容,所以我需要返回

一方面,我被告知C#中的异常是“昂贵的”,但另一方面,我被困在如何实现这一点上

我的问题是:我正在制作一个
派生,它包装了一个
网络流
。现在,我面临的问题是:
Read(byte[]buffer,int offset,int count)
。从函数的
文档:

返回:

。。。或者,如果已到达流的末尾,则为零(0)

问题是,在我实现的协议中,远程端可以发送“记录结束”令牌或“请响应”令牌。显然,如果这种情况发生在
Read()
的开头,这会导致问题,因为我需要从函数返回,而且我没有读取任何内容,所以我需要返回0,这意味着流已完成,但它不是。。。在这种情况下,
EndOfRecordException
或类似异常是否合理?在这种情况下,当遇到这个令牌时,应该抛出它(在
Read()
调用的开始,并通过提前返回来确保这些令牌始终在开始处),这样就有了处理这些令牌的某种模式


编辑:不管它值多少钱,这些代币通常每秒经过3-10次。我最多也不会期望每秒超过25次。

异常并不真的那么昂贵,但它们也不一定是管理预期/正常流量的最佳方式


对我来说,听起来你并没有真正实现一个
——你是在将一个流封装到一个“阅读器”中。我可能倾向于使用合适的方法编写特定于协议的读卡器类,以检测记录的结尾,或者使用
尝试…
方法获取数据或返回false。

异常并没有那么昂贵,但它们也不一定是管理预期/正常流的最佳方法


对我来说,听起来你并没有真正实现一个
——你是在将一个流封装到一个“阅读器”中。我可能倾向于编写一个特定于协议的读卡器类,使用合适的方法来检测记录的结尾,或者使用
尝试…
方法来获取数据或返回false。

如果您的类与记录有关,听起来您不应该真正从
流派生。流通常根本不解释它们的数据——它们只是数据从一个地方到另一个地方的传输机制

Java中也出现过类似于
ZipInputStream
的情况,当单个
InputStream
实际上包含多个流时,结果会非常混乱,您可以在它们之间跳过。根据我的经验,这样的API使用起来很糟糕。提供一个单独的类来实现“记录分割”,它可以为记录中的数据提供一个流,这对我来说听起来更干净。然后,每个流可以与正常流保持一致的行为。不需要新的例外情况


然而,我只是根据有限的信息猜测您的上下文。如果你能提供更大范围的细节,那会有所帮助。

如果你的班级关心记录,听起来你不应该真正从
流中派生。流通常根本不解释它们的数据——它们只是数据从一个地方到另一个地方的传输机制

Java中也出现过类似于
ZipInputStream
的情况,当单个
InputStream
实际上包含多个流时,结果会非常混乱,您可以在它们之间跳过。根据我的经验,这样的API使用起来很糟糕。提供一个单独的类来实现“记录分割”,它可以为记录中的数据提供一个流,这对我来说听起来更干净。然后,每个流可以与正常流保持一致的行为。不需要新的例外情况


然而,我只是根据有限的信息猜测您的上下文。如果你能提供更大范围的细节,那会有所帮助。

从性能角度看,这不是什么大问题,但仍然。。。例外是为了例外。“不寻常”的情况。如果这就是底层流的行为方式,那么您的流应该能够处理它。如果可以,它应该自己处理。如果没有,您可以让用户设置一些回调或当您收到“请响应”令牌时将被调用的东西。

这在性能方面不是什么大问题,但仍然。。。例外是为了例外。“不寻常”的情况。如果这就是底层流的行为方式,那么您的流应该能够处理它。如果可以,它应该自己处理。如果没有,您可以让用户设置一些回调或当您收到“请响应”令牌时将被调用的东西。

我认为
-派生类应该只处理流问题,并遵守
语义契约。所有高级逻辑(解释EOF和EOR标记)都应该放在其他类中。

我认为
-派生类应该只处理流问题,并遵守
语义契约。所有高级逻辑(解释EOF和EOR令牌)都应该放在其他类中。

也许您可以创建一个返回的枚举,该枚举可以包含EndOfRecord、EndOfStream、ReadOk或任何您需要的项


实际读取的数据可以作为out参数传递。

也许您可以创建一个返回的枚举,该枚举可以包含EndOfRecord、EndOfStream、ReadOk或任何您需要的项目


实际读取的数据可以作为out参数传递。

无法更改函数签名,因为它是在基流类中定义的。无法更改函数签名,因为它是在基流类中定义的。