Sla*_*uma 10 .net c# exception
在我的代码中,我经常遇到这样的情况:
public void MyMethod(string data)
{
AnotherClass objectOfAnotherClass = GetObject(data);
if (objectOfAnotherClass == null)
throw new WhatExceptionType1("objectOfAnotherClass is null.");
if (objectOfAnotherClass.SomeProperty < 0)
throw new WhatExceptionType2("SomeProperty must not be negative.");
}
Run Code Online (Sandbox Code Playgroud)
想象一下,GetObject使用一些不受我控制的外部库,null如果没有对象data存在则返回该库,并将负数SomeProperty视为有效状态,因此不会抛出异常.进一步设想,MyMethod如果不工作objectOfAnotherClass,并没有什么意义了负SomeProperty.
WhatExceptionType1/2投入这种情况的正常例外是什么?
基本上我有四个选择:
1)InvalidOperationException,因为MyMethod在上述条件下没有意义.另一方面,指南(以及VS中的Intellisense)表示如果方法所属的对象处于无效状态,则应抛出InvalidOperationException.现在对象本身不处于无效状态.相反,输入参数data和基于该参数的一些其他操作导致MyMethod不能再操作的情况.
2)ArgumentException,因为有方法的值data可以使用和方法不能的其他值.但我无法通过data单独检查来检查这一点,在决定之前我必须调用其他操作.
3)Exception,因为我不知道使用哪个其他异常类型,并且因为所有其他预定义异常都觉得太专业并且不适合我的情况.
4)MyCustomException(我自己的异常类型派生自Exception).这似乎总是一个选项,但我担心当我开始遵循这种模式时,我必须为许多不同的错误条件定义许多特殊的异常类.
还有其他更好的选择吗?支持或反对这些选择的论据是什么?
感谢您提前的反馈!
如果存在有意义的内置异常,我会使用它们.如果没有,那么滚动自己的异常是有意义的 - 即使它是一个扩展Exception的空类 - 因为这允许您检测特定的异常类型.例如,如果你只是抛出异常,你怎么知道异常是因为objectOfAnotherClass是null,并且它不是引发了一些异常GetObject?
总而言之:具体的异常更好,因为您可以(可能)诊断并从特定情况中恢复.因此,使用内置的.NET异常(如果它们足够),或者滚动自己的异常.
编辑:我应该澄清,我很少使用现有的异常并在其中添加消息.如果异常类型告诉您错误,而不是必须调试,生成异常,然后检查消息以查看问题是什么,它会使您的代码更具可读性.
使用内置异常类型时要小心......它们对.NET框架有非常具体的含义,除非你使用它具有完全相同的含义,否则最好自己滚动(+1到John Saunders Serializeable).
InvalidOperationException 有意思:
方法调用对于对象的当前状态无效时引发的异常.
例如,如果您调用SqlConnection.Open(),InvalidOperationException则在未指定数据源的情况下获得. InvalidOperationException不适合您的方案.
ArgumentException也不合适.创建失败objectOfAnotherClass可能与传入的错误数据无关.假设它是文件名,但GetObject()没有读取文件的权限.在编写方法时,无法知道调用GetObject()失败的原因,并且可以说最好的是返回的对象为null或无效.
Exception通常只是一个坏主意......它让调用者完全不知道为什么该方法无法创建对象.(就此而言,只有一个catch (Exception ex) {..}也是一个坏主意)
您需要能够清楚地识别出错的异常,这意味着要创建自己的异常.尽量保持通用,以避免1,000个自定义异常.我建议:
ObjectCreateException: // The call to GetObject() returned null<br />
InvalidObjectException: // The object returned by GetObject() is invalid
// (because the property < 0)
Run Code Online (Sandbox Code Playgroud)
感谢投票〜我想我会添加一些我们写过的自定义异常的例子.
请注意,您实际上不需要向方法添加任何代码,因为自定义异常实际上并没有做出与其基类不同的任何操作.他们只代表不同的东西.第二个例子确实为异常添加了一个属性,因此有代码支持它(包括构造函数).
第一个是我们所有例外的通用基础; 规则"不要捕获一般异常"适用(尽管我们仍然这样做......它允许我们区分我们生成的异常和框架抛出的异常).第二个是一个更具体的异常,它源自Gs3Exception并序列化自定义属性.
.NET开发团队决定ApplicationException没有现实世界的价值并且不赞成它,但我的纯粹主义者总是喜欢它,所以它仍然存在于我的代码中.但是,在这里,它确实没有增加任何价值,只增加了继承层次的深度.所以可以直接从中继承Exception.
/// <summary>
/// A general, base error for GS3 applications </summary>
[Serializable]
public class Gs3Exception : ApplicationException {
/// <summary>
/// Initializes a new instance of the <see cref="Gs3Exception"/> class </summary>
public Gs3Exception() {}
/// <summary>
/// Initializes a new instance of the <see cref="Gs3Exception"/> class </summary>
/// <param name="message">A brief, descriptive message about the error </param>
public Gs3Exception(string message) : base(message) {}
/// <summary>
/// Initializes a new instance of the <see cref="Gs3Exception"/> class
/// when deserializing </summary>
/// <param name="info">The object that holds the serialized object data </param>
/// <param name="context">The contextual information about the source or
/// destination.</param>
public Gs3Exception(SerializationInfo info, StreamingContext context) : base(info, context) { }
/// <summary>
/// Initializes a new instance of the <see cref="Gs3Exception"/> class
/// with a message and inner exception </summary>
/// <param name="Message">A brief, descriptive message about the error </param>
/// <param name="exc">The exception that triggered the failure </param>
public Gs3Exception(string Message, Exception exc) : base(Message, exc) { }
}
/// <summary>
/// An object queried in an request was not found </summary>
[Serializable]
public class ObjectNotFoundException : Gs3Application {
private string objectName = string.Empty;
/// <summary>
/// Initializes a new instance of the <see cref="ObjectNotFoundException"/> class </summary>
public ObjectNotFoundException() {}
/// <summary>
/// Initializes a new instance of the <see cref="ObjectNotFoundException"/> class </summary>
/// <param name="message">A brief, descriptive message about the error</param>
public ObjectNotFoundException(string message) : base(message) {}
/// <summary>
/// Initializes a new instance of the <see cref="ObjectNotFoundException"/> class </summary>
/// <param name="ObjectName">Name of the object not found </param>
/// <param name="message">A brief, descriptive message about the error </param>
public ObjectNotFoundException(string ObjectName, string message) : this(message) {
this.ObjectName = ObjectName;
}
/// <summary>
/// Initializes a new instance of the <see cref="ObjectNotFoundException"/> class.
/// This method is used during deserialization to retrieve properties from
/// the serialized data. </summary>
/// <param name="info">The object that holds the serialized object data.</param>
/// <param name="context">The contextual information about the source or
/// destination.</param>
public ObjectNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) {
if (null != info) {
this.objectName = info.GetString("objectName");
}
}
/// <summary>
/// When serializing, sets the <see cref="T:System.Runtime.Serialization.SerializationInfo"/>
/// with information about the exception. </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds
/// the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="info"/> parameter is a null reference (Nothing in Visual Basic) </exception>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="*AllFiles*" PathDiscovery="*AllFiles*"/>
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="SerializationFormatter"/>
/// </PermissionSet>
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter)]
public override void GetObjectData(SerializationInfo info, StreamingContext context) {
base.GetObjectData(info, context);
// 'info' guaranteed to be non-null (base.GetObjectData() will throw an ArugmentNullException if it is)
info.AddValue("objectName", this.objectName);
}
/// <summary>
/// Gets or sets the name of the object not found </summary>
/// <value>The name of the object </value>
public string ObjectName {
get { return objectName; }
set { objectName = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
PS:在任何人打电话给我之前,基础Gs3Exception没有增加价值的原因ApplicationException是企业库异常处理应用程序块...通过具有应用程序级基本异常,我们可以为抛出的异常创建一般日志记录策略直接通过我们的代码.
| 归档时间: |
|
| 查看次数: |
4612 次 |
| 最近记录: |