0xC*_*ABE 108 c# exception unreachable-code
此代码是读取和写入ODBC连接的数据库的应用程序的一部分。它在数据库中创建一条记录,然后检查是否已成功创建记录,然后返回true
。
我对控制流的理解如下:
command.ExecuteNonQuery()
有记录表明,Invalid?Operation?Exception
当“方法调用对该对象的当前状态无效”时,将引发。因此,如果发生这种情况,该try
块的执行将停止,该finally
块将被执行,然后return false;
在底部执行。
但是,我的IDE声称该return false;
代码不可访问。而且似乎是事实,我可以删除它,并且可以毫无抱怨地进行编译。但是,对我来说,似乎抛出上述异常的代码路径没有返回值。
private static bool createRecord(String table,
IDictionary<String,String> data,
System.Data.IDbConnection conn,
OdbcTransaction trans) {
[... some other code ...]
int returnValue = 0;
try {
command.CommandText = sb.ToString();
returnValue = command.ExecuteNonQuery();
return returnValue == 1;
} finally {
command.Dispose();
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
我在这里理解的错误是什么?
AAA*_*ddd 149
检测到无法访问的代码
编译器检测到永远不会执行的代码。
就是说,编译器通过“ 静态分析”了解到了无法达到的程度,并从编译的IL中完全忽略了它(因此请注意)
注意:您可以通过尝试使用调试器进入“无法访问的代码”或使用IL Explorer来证明这一事实。
该finally
可上运行异常,(尽管这一边),它不会改变的事实(在这种情况下),它仍然是一个未捕获的异常。嗯,最后一个return
永远不会受到打击。
如果您希望代码继续到最后return
,则唯一的选择是捕获异常;否则,请执行以下步骤。
如果您不这样做,则将其保留原样,然后删除return
。
例
try
{
command.CommandText = sb.ToString();
returnValue = command.ExecuteNonQuery();
return returnValue == 1;
}
catch(<some exception>)
{
// do something
}
finally
{
command.Dispose();
}
return false;
Run Code Online (Sandbox Code Playgroud)
引用文档
通过使用finally块,您可以清除try块中分配的所有资源,即使try块中发生异常,也可以运行代码。通常,当控制离开try语句时,finally块的语句运行。可以通过正常执行,执行break,continue,goto或return语句,或从try语句传播异常来进行控制转移。
在处理的异常内,可以保证关联的finally块可以运行。但是,如果未处理异常,则finally块的执行取决于如何触发异常展开函数。反过来,这取决于计算机的设置方式。
通常,当未处理的异常结束应用程序时,是否运行finally块并不重要。但是,如果在即使在那种情况下都必须运行的finally块中有语句,一种解决方案是在try-finally语句中添加catch块。或者,您可以捕获可能在调用堆栈上方的try-finally语句的try块中引发的异常。也就是说,您可以在调用包含try-finally语句的方法的方法中,在调用该方法的方法中或在调用堆栈中的任何方法中捕获异常。如果未捕获到异常,则finally块的执行取决于操作系统是否选择触发异常展开操作。
最后
使用支持IDisposable
接口的任何东西(旨在释放非托管资源)时,可以将其包装在using
语句中。编译器将在对象上生成try {} finally {}
和内部调用Dispose()
Pat*_*man 86
将执行finally块,然后执行return false;在底部。
错误。finally
不会吞下异常。它很荣幸,并且异常将被正常抛出。它将仅在代码块结束之前的finally中执行代码(有无异常)。
如果您希望吞下异常,则应使用catch
其中没有no 的块throw
。
Sin*_*atr 27
警告是因为您没有使用,catch
并且您的方法基本上是这样编写的:
bool SomeMethod()
{
return true;
return false; // CS0162 Unreachable code detected
}
Run Code Online (Sandbox Code Playgroud)
由于finally
仅用于处置,因此首选的解决方案是利用using
模式:
using(var command = new WhateverCommand())
{
...
}
Run Code Online (Sandbox Code Playgroud)
足以确保Dispose
将要调用的内容。确保在成功执行代码块之后或在调用堆栈中的某些catch
中断(父调用已关闭,对吗?)之后(在此之前)被调用。
如果不是要处理的话
try { ...; return true; } // only one return
finally { ... }
Run Code Online (Sandbox Code Playgroud)
足够了,因为您将永远不必false
在方法末尾返回(不需要该行)。你的方法是执行命令(任一返回结果true
或false
)或将抛出一个异常,否则。
还考虑通过包装预期的异常来抛出自己的异常(签出InvalidOperationException构造函数):
try { ... }
catch(SomeExpectedException e)
{
throw new SomeBetterExceptionWithExplanaition("...", e);
}
Run Code Online (Sandbox Code Playgroud)
这通常用于对调用者说一些比嵌套调用异常所讲的更有意义(有用)的东西。
大多数时候,您实际上并不关心未处理的异常。有时,finally
即使未处理异常,也需要确保调用了该方法。在这种情况下,您只需自己抓住它并重新抛出(请参阅此答案):
try { ... }
catch { ...; throw; } // re-throw
finally { ... }
Run Code Online (Sandbox Code Playgroud)
Dmi*_*nko 13
看来,您正在寻找这样的东西:
private static bool createRecord(string table,
IDictionary<String,String> data,
System.Data.IDbConnection conn,
OdbcTransaction trans) {
[... some other code ...]
// Using: do not call Dispose() explicitly, but wrap IDisposable into using
using (var command = ...) {
try {
// Normal flow:
command.CommandText = sb.ToString();
// True if and only if exactly one record affected
return command.ExecuteNonQuery() == 1;
}
catch (DbException) {
// Exceptional flow (all database exceptions)
return false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这finally
不会吞噬任何异常
finally {
// This code will be executed; the exception will be efficently re-thrown
}
// And this code will never be reached
Run Code Online (Sandbox Code Playgroud)
您没有catch
阻止,因此仍然引发异常,阻止返回。
将执行finally块,然后执行return false;在底部。
这是错误的,因为将执行finally块,然后会有未捕获的异常。
finally
块用于清除,它们不捕获异常。在返回之前引发异常,因此,永远不会到达返回,因为在此之前引发了异常。
您的IDE是正确的,它将永远不会到达,因为将引发异常。只有catch
块能够捕获异常。
阅读文档,
通常,当未处理的异常结束应用程序时,是否运行finally块并不重要。但是,如果在即使在那种情况下都必须运行的finally块中有语句,则一种解决方案是在try-finally语句中添加catch块。或者,您可以捕获可能在调用堆栈上方的try-finally语句的try块中引发的异常。也就是说,您可以在调用包含try-finally语句的方法的方法中,在调用该方法的方法中或在调用堆栈中的任何方法中捕获异常。如果未捕获到异常,则finally块的执行取决于操作系统是否选择触发异常展开操作。
这清楚地表明,finally并非旨在捕获异常,并且如果在该catch
语句之前有一个空语句,那您将是正确的finally
。
引发异常时,堆栈将展开(执行将移出函数)而不会返回值,并且函数上方的堆栈帧中的任何catch块都将捕获异常。
因此,return false
将永远不会执行。
尝试手动引发异常以了解控制流:
try {
command.CommandText = sb.ToString();
returnValue = command.ExecuteNonQuery();
// Try this.
throw new Exception("See where this goes.");
return returnValue == 1;
} finally {
command.Dispose();
}
Run Code Online (Sandbox Code Playgroud)
在您的代码上:
private static bool createRecord(String table, IDictionary<String,String> data, System.Data.IDbConnection conn, OdbcTransaction trans) {
[... some other code ...]
int returnValue = 0;
try {
command.CommandText = sb.ToString();
returnValue = command.ExecuteNonQuery();
return returnValue == 1; // You return here in case no exception is thrown
} finally {
command.Dispose(); //You don't have a catch so the exception is passed on if thrown
}
return false; // This is never executed because there was either one of the above two exit points of the method reached.
}
Run Code Online (Sandbox Code Playgroud)
将执行finally块,然后执行return false;在底部
这是您逻辑上的缺陷,因为该finally
块不会捕获异常,并且永远不会到达最后一个return语句。
归档时间: |
|
查看次数: |
13796 次 |
最近记录: |