我有一些看起来像这样的UI代码:
try
{
SomeClass classInstance = new SomeClass(someId);
}
catch (Exception exception)
{
// Content wasn't created, show a message, stop processing
return;
}
似乎添加了try catch,因为SomeClass的构造函数会弹出,如果它接收的someId无效,并且在数据库中找不到数据。
最近通过FXCop运行此代码,它警告不要使用常规Exception,但所有SomeClass都会抛出一个新的Exception,并带有一条消息,说它无法初始化。
我想问题是类构造函数应该有它自己的自定义异常,然后我可以在我的UI中处理,但我想知道我还能对上面的代码做什么来处理异常,满足FXCop的要求?
答案 0 :(得分:4)
FxCop的规则存在是因为上面的catch (Exception)
块捕获了所有可能的异常,包括您可能无法以有用的方式捕获的StackOverflowException
等低级异常。
正确的方法肯定是抛出一种更具体的类型:您发明的一种类型,或者与您的情况非常匹配的现有.NET框架异常类型。 (如果有疑问,我通常会去InvalidOperationException
。)
或者,您可以在捕获时检查确切的异常类型。这不会阻止FxCop警告,但它应该解决潜在的问题:
catch (Exception exception)
{
if (exception.GetType() == typeof(Exception))
{
// Content wasn't created, show a message, stop processing
return;
}
else
{
// Some other exception type that wasn't thrown from our code -
// delegate to a higher-level exception handler
throw;
}
}
答案 1 :(得分:3)
您不需要自定义例外;在给定的情况下,只使用框架中已存在的数十个中的一个。如果someId
不好,请抛出ArgumentException
- 这就是它的用途。如果某些东西不为null,则会出现NullReferenceException
;只是让它被抛出。等等。抛出一个简单的Exception
有点像说“出了问题 - 阅读信息以获取详细信息”而不是“这出错”。
FxCop正在抱怨catch (Exception)
,因为它常常被滥用来吞没所有异常,而不是让它们传播并由知道如何操作的代码处理。你应该能够说出抛出什么类型的异常并捕获它们,同时让那些你不认识的异常进入调用堆栈。
答案 2 :(得分:2)
您应该修复类构造函数。投掷Exception
永远不会一个好主意。
但是,要暂时解决这个问题(因为这是一个可怕的,不可靠的黑客攻击),你可以检查异常的消息,而不是你期望的消息:
catch (Exception exception)
{
if (exception.Message == "whatever your class sets the message to")
// Content wasn't created, show a message, stop processing
return;
else
// Any other exception should bubble
throw;
}
答案 3 :(得分:0)
使用InvalidOperationException
代替投掷Exception
听起来似乎是明智的。
答案 4 :(得分:0)
如果FXCop不喜欢处理一般的Exception(我倾向于同意),那么也许你可以访问SomeClass的源代码。修改构造函数以抛出更具体的异常,例如ArgumentOutOfRangeException或一些自定义异常。
在这种情况下,您的代码将如下所示:
try
{
SomeClass classInstance = new SomeClass(someId);
}
catch(ArgumentOutOfRangeException exception)
{
// Content wasn't created, show a message, stop processing
return;
}
答案 5 :(得分:0)
正如许多其他人所说,构造函数不应该抛出一个裸Exception
。看到构造函数从DB检索数据并根据结果抛出,最好的解决方案是创建自己的异常类。
在Visual Studio中创建异常非常容易。只需输入Exception
并按 TAB 即可。然后,它将使用所需的构造函数(所有四个)创建异常类。不要害怕创建不那么做的课程,这就是他们的目的。
这就是我写这个课的方式:
public class SomeClass {
public SomeClass(int someId) {
if (someId < 0) //validation on the ID, can it be negative?
throw new ArgumentException("someId", "ID cannot be negative");
//Perform DB operation
if (/*DB error - not found*/)
throw new DataNotFoundException("Cannot find record with ID " + someId);
}
}
[Serializable]
public class DataNotFoundException : Exception {
public DataNotFoundException() { }
public DataNotFoundException(string message) : base(message) { }
public DataNotFoundException(string message, Exception inner) : base(message, inner) { }
protected DataNotFoundException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}