如何故意忽略返回值
在某些使用C / C ++的情况下,我可以在语法上向编译器指示故意忽略返回值:
int SomeOperation() { // Do the operation return report_id; } int main() { // We execute the operation, but in this particular context we // have no use of the report id returned. (void)SomeOperation(); }
我觉得这是一个公平的做法,首先是因为大多数编译器不会在这里产生警告,其次是因为它向未来的开发人员明确表明作者有意识地选择忽略回报。 它使作者的思想痕迹不含糊。
据我所知,C#编译器不会抱怨隐式忽略返回值,但我想知道是否有类似的约定用于向其他开发人员明确指示。
回答这里的一些人质疑这个约定的实际使用(或者它会显示糟糕的设计以使方法具有潜在的不重要的返回值)。
一个真实的.NET示例(我可能应该从一开始就基于问题)是Mutex::WaitOne()
重载,它不带参数。 只有在安全获取互斥锁时它才会返回,否则它永远不会返回。 布尔返回值是针对其他重载的,您可能在返回时最终没有拥有互斥锁。
所以在我的推理中,我想在我的multithreading代码中指出我已经选择忽略返回:
Mutex mtx = new Mutex(); (void)mtx.WaitOne();
因为返回值永远不会是true
。
我只能想到一种情况,即在C#中不允许忽略“返回值”:发生错误时。 这应该通过抛出exception来提供,这使得它不可能被忽略。
在其他情况下,忽略返回值是(或更好:必须)完全安全且完全没有臭味。
我还是看不出这一点。 为什么要改进代码呢? 您指定通过不将返回值分配给变量来忽略返回值。
- 如果你的代码中不需要这个值,一切都很好。
- 如果需要,您将无法编写代码。
- 如果存在必须处理的特殊情况且绝不能隐式忽略,则应抛出exception。
- 如果被调用的方法没有返回值并稍后获取它,则必须将其设计为不破坏忽略它的现有代码。 现有的调用代码不会更改。
我忘了案吗?
如果您想向其他开发人员表明并明确表示有意忽略返回值,请对其进行评论。
SomeMethod(); // return value ignored - $REASON
Microsoft C#编译器不会在忽略返回时生成警告。 它不需要,因为有一个垃圾收集器,所以不会有任何内存泄漏,因为忽略返回的对象(当然,除非它们是IDisposable)。 因此,不需要显式“覆盖”编译器。
编辑:另外,我认为“可维护性”问题更像是文档和命名实践问题。 我知道这只是一个例子,但你不会指望一个名为SomeOperation
的方法返回一个ReportId
。 但是,您会期望GetReportId
方法返回ReportId
而不会产生很多副作用。 实际上,忽略名为GetReportId
的方法的返回值会相当奇怪。 因此,请确保您很好地命名您的方法,人们不会怀疑您的函数调用的效果。
编辑2:在这个互斥体的例子中,我认为正确的用法实际上不会忽略返回值。 即使当前实现永远不会返回false,我认为仍然检查返回值是一个好习惯,以防万一您将来最终使用另一个实现,或者它们会在.NET Framework的未来版本中更改行为或东西:
if (mutex.WaitOne()) { // Your code here } else { // Optionally, some error handling here }
在C#7.0之后,您可以使用discard运算符“_”指示故意忽略的返回值。
int SomeOperation() { return report_id; } int main() { _ = SomeOperation(); }
有关详细信息,请在此处查看Microsoft文档。
object dummy = JustDontCare();
没有标准的约定我知道。
但是我很难找到一个需要这个的好理由。 听起来SomeOperation()应该是两个独立的方法。 你有一个真正应该这样做的方法的例子吗? 如果一个方法被忽略,为什么一个方法会打扰返回结果呢?
有时候能够输入(void)来指示未来的编码器是否能够完美地知道它返回的东西,并且你故意忽略它。
也就是说,C#编译器会在语法上出错。
我见过:
var notUsed = SomeOperation();
虽然不是那么喜欢它。
.Net中的约定是,如果你不存储或使用返回值意味着你隐式忽略它,那么就没有明确的约定,并且API通常被设计为通常可以忽略返回值,但布尔值除外代表失败,成功状态。
但即使在表示成功/失败状态的布尔返回值的情况下,约定是如果忽略返回值(不使用它),则意味着代码不依赖于先前调用的成功状态。