Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 正在引发正确类型的异常_C#_.net_Exception - Fatal编程技术网

C# 正在引发正确类型的异常

C# 正在引发正确类型的异常,c#,.net,exception,C#,.net,Exception,在我的代码中,我经常遇到这样的情况: public void MyMethod(string data) { AnotherClass objectOfAnotherClass = GetObject(data); if (objectOfAnotherClass == null) throw new WhatExceptionType1("objectOfAnotherClass is null."); if (objectOfAnotherClass

在我的代码中,我经常遇到这样的情况:

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.");
}
public void MyMethod(字符串数据)
{
其他类的另一个类objectOtherClass=GetObject(数据);
if(objectOfOtherClass==null)
抛出新的WhatExceptionType1(“ObjectOfOtherClass为null”);
if(objectOfOtherClass.SomeProperty<0)
抛出新的WhatExceptionType2(“SomeProperty不能为负”);
}
假设
GetObject
使用了一些不受我控制的外部库,如果
data
不存在对象,则该库返回
null
,并将负的
SomeProperty
视为有效状态,因此不会引发异常。进一步想象一下,如果没有其他类的
对象,则
MyMethod
无法工作,如果使用负的
SomeProperty
,则没有意义

在这种情况下,
WhatExceptionType1/2
应该抛出哪些异常

基本上我有四个选择:

  • 1)
    InvalidOperationException
    ,因为在上述条件下,
    MyMethod
    没有意义。另一方面,指南(以及VS中的Intellisense)指出,如果方法所属的对象处于无效状态,则应抛出InvalidOperationException。现在,对象本身没有处于无效状态。相反,输入参数
    data
    和基于此参数的一些其他操作会导致
    MyMethod
    无法再运行的情况

  • 2)
    ArgumentException
    ,因为有方法可以使用的
    数据值和方法不能使用的其他值。但是我不能通过单独检查
    数据来检查这一点,我必须在决定之前调用其他操作

  • 3)
    异常
    ,因为我不知道要使用哪种其他异常类型,而且因为所有其他预定义的异常都感觉过于专业化,不适合我的情况

  • 4)
    MyCustomException
    (我自己的异常类型派生自
    exception
    )。这似乎总是一个选项,但我担心,当我开始遵循此模式时,我必须为许多不同的错误条件定义许多特殊的异常类

还有其他更好的选择吗?赞成或反对这些选择的理由是什么


提前感谢您的反馈

使用ObjectNotFoundException怎么样。这将正确地描述情况。

如果存在有意义的内置异常,我将使用它们。如果不是,则滚动您自己的异常是有意义的——即使它是扩展异常的空类——因为这允许您检测特定的异常类型。例如,如果您刚刚抛出异常,您如何知道异常是因为其他类的
objectofotherclass
为null,并且它不是在
GetObject
中引发的某个异常

总之:特定异常更好,因为您可以(潜在地)诊断特定情况并从中恢复。因此,请使用内置的.NET异常(如果它们足够),或者滚动您自己的异常


编辑:我应该澄清,我很少使用现有的异常,并在其中添加消息。如果异常类型告诉您错误,而不必调试、生成异常,然后检查消息以了解问题所在,则会使代码更具可读性。

这实际上取决于您计划如何在应用程序中处理异常。自定义异常在try/catch情况下很好,但try/catch也很昂贵。如果您不打算捕获和处理自定义异常,那么:抛出新异常(“索引超出范围:SomeProperty不能为负值”);与自定义异常一样有用

public class InvalidStateException : ApplicationException
{
   ...
}
在代码中:

// test for null
if(objectOfAnotherClass == null) throw new NullReferenceException("Object cannot be null");

// test for valid state
if(objectOfAnotherClass.SomeProperty < 0) throw new InvalidStateException("Object is in an invalid state");
//测试空值
如果(ObjectOfOtherClass==null)抛出新的NullReferenceException(“对象不能为null”);
//有效状态测试
如果(ObjectOfOtherClass.SomeProperty<0)抛出新的InvalidStateException(“对象处于无效状态”);

如果不是两种情况,至少在第一种情况下,我的投票将是
ArgumentException
;ArgumentExceptions应该抛出,引号是“当提供给方法的参数之一无效时”。如果MyMethod无法按照MyMethod的预期使用参数
data
创建另一个类的有效实例,则该参数在MyMethod中无效


请理解,除非您计划捕获不同类型的异常并以不同的方式处理它们,否则抛出哪个异常实际上并不重要。有些异常(如ArgumentNullException)基于很少的信息创建自定义消息,因此易于设置和本地化,而另一些异常(如SQLException)则有关于出错原因的更具体的数据,但如果您只想抛出一个说“Oops!”的异常,那么所有这些都是多余的。

首先,对错误进行分类。埃里克·利珀特(Eric Lippert)是我见过的最好的分类:致命的、骨瘦如柴的、令人烦恼的和外源性的。你的例外不会是致命的;这可能是一个:愚蠢的,烦躁的,或外生的

如果您可以说对于正确的输入
name
,您知道
GetObject
将返回一个对您的方法有意义的对象,那么这个错误就是愚蠢的。换句话说,导致这些异常的唯一原因是调用
MyMethod
的代码中的错误。在这种情况下,您使用的异常类型实际上并不重要,因为您无论如何都不应该在生产中看到它——
ArgumentException
(如果问题出在
name
)或
invalidoOperationexception
(如果问题出在定义
MyMethod
的对象的状态)在这种情况下是不错的选择,但不应记录特定的异常类型(或
ObjectCreateException:   // The call to GetObject() returned null<br />
InvalidObjectException:  // The object returned by GetObject() is invalid 
                         // (because the property < 0)
/// <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; }
    }

}
public void MyMethod(AnotherClass data)
{
    if (data == null)
        throw new ArgumentNullException("data is null.");

    if (data.SomeProperty < 0)
        throw new ArgumentException("data.SomeProperty must not be negative.");

    ...
}