c# - 应该在哪里抛出异常?

标签 c# .net exception

我有一个看起来像下面这样的类:

public class StackOverflowQuestion {

    private string _question;

    public string Question {
        get { return _question;  }
        set { _question = value; }
    }

    public StackOverflowQuestion(string question) {
        _question = question;
    }

    public override string ToString() {
        return _question;
    }
}

现在,值“question”不允许为 null 或空,并且应该通过 ArgumentNullException 通知用户 - 但应该将其抛出到哪里?根据“快速失败”原则 -> 无处不在。

public class StackOverflowQuestion {

    private string _question;

    public string Question {
        get { return _question;  }
        set { 
           if(!String.IsNullOrEmpty(value))
                _question = value
            else throw new ArgumentNullException("value");
        }
    }

    public StackOverflowQuestion(string question) {
        if(!String.IsNullOrEmpty(question))
            _question = question;
        else throw new ArgumentNullException("question");
    }

    public override string ToString() {
        if(!String.IsNullOrEmpty(_question)) return _question;
        else throw new ArgumentNullException("_question");
    }
}

现在这显然是荒谬的,而且极其重复。但似乎是对的:如果通过.ctor设置值,短暂检查后直接失败。当它通过属性进行设置时,它会在短暂检查后直接失败。但是谁会期望 setter 出现异常呢?当我输出字符串时,我期待一个字符串,而不是很久以前就应该发生的事情的异常,但再次强调:如果它是错误的,它应该尽快失败,即使“很快”已经很晚了。

那么,唯一的异常处理应该在哪里进行呢?我是在寻求“最佳实践”,还是一种品味?

最佳答案

由于 _question 是私有(private)的,因此无需在 ToString() 中检查它是否为 null(除非您只是在检查自己的代码)。

您可以通过让构造函数使用属性 setter 来避免在构造函数中进行检查。因此,我建议:

public class StackOverflowQuestion {

    private string _question;

    public string Question {
        get { return _question;  }
        set { 
           if(string.IsNullOrEmpty(value))
                // to make this more transparent when thrown through the constructor, it might
                // be preferable to throw a real error message like "Question: cannot be null or empty"
                throw new ArgumentException("value");
           this._question = value;
        }
    }

    public StackOverflowQuestion(string question) {
        this.Question = question;
    }

    public override string ToString() {
        return this.Question;
    }
}

需要注意的几点: 1. 您应该为空字符串抛出 ArgumentException 而不是 ArgumentNullException(如果您愿意,您可以进行 2 次检查并且仍然为 null 抛出 ArgumentNullException)。 2. 虽然该方法使用的代码较少,但一个缺点是用户收到的错误消息比将 null 传递给构造函数时稍差一些,因为故障发生在 2 层深度而不是一层。

关于c# - 应该在哪里抛出异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17722356/

相关文章:

c# - 通过 .NET 将参数传递给 XSLT 样式表

.net - Visual Studio 2010 - 构建性能问题后(应用程序启动需要很长时间)

c# - 以固定或最小间隔处理 Rx 事件

c# - itextsharp document.close 上的堆栈溢出异常

c# - 匿名类型和泛型

c# - 计算测量转换

c# - 如果内部发生异常,锁定的对象是否会保持锁定状态?

java - 如何解决IllegalArgumentException : Property is not indexed

c# - vs 2010中一个解决方案下的多项目调试

.net - 在 vb.net 应用程序中打开图像后无法删除图像