在这种情况下,我应该如何处理无效的用户输入?

时间:2009-10-06 19:12:36

标签: c# validation exception null

我正在编写一个几何建模程序的插件,我有一个基于Curve对象的抽象类。如果曲线是平面的,闭合的并且自身不相交,则该曲线仅被视为有效。

然后我有一系列其他方法来引用这条曲线,它可以做一些表面,或者将它拉伸到一个体积中。如果在BaseCurve无效时调用它们,这些方法将抛出异常。现在,如果用户使其中一条曲线无效,我的程序就会崩溃,而我正在试图找出让我的程序处理这个无效输入的最佳方法。

这是我班级的样子:

public abstract class AbsCurveBasedObject
{
    public abstract Curve BaseCurve
    {
        get;
    }

    public bool BaseCurveIsValid
    {
        get
        {
            Curve c = this.BaseCurve;
            ...
            //checks that curve is valid
            ...
            return true/false;
        }
    }

    public Surface GetSurface()
    {
         Curve c = this.BaseCurve();
         ...
         //magic that converts c to a surface
         //exception is thrown if c is invalid
         ...
         return surface;
    }

    public Surface GetVolume()
    {
         Surface s = this.GetSurface();
         ...
         //magic that converts s into a volume
         ...
         return volume;
    }
}

如果曲线无效或者我应该抛出异常,我不确定 GetSurface()是否应返回 NULL

基本曲线无效并不出人意料,因为我知道用户在使用我的程序时最终会创建无效曲线。我的理解是,当程序达到意外发生并且不知道如何继续的程度时,通常只应抛出异常?

如果曲线无效,我应该只从GetSurface()返回NULL,然后让GetSurface()的每个方法在GetSurface()的情况下返回null吗?这似乎更难调试。我知道我最终会忘记检查返回值是否为NULL并最终得到一些ArgumentNullException,它跟踪一直回到AbsCurveBasedObject.GetSurface()

因此,如果用户有一些如何使基本曲线属性无效,那么在整个地点跟踪中使用if / else或try / catch块会更好吗?

3 个答案:

答案 0 :(得分:2)

理想情况下,如果可以避免异常,你永远不想抛出异常。但是,这并不一定意味着返回null是正确的做法!这可能是错误的。

以这种方式看待它。您的代码可能如下所示:

Blah MakeMeABlah(Foo foo)
{
  if (!IsValid(foo)) throw new InvalidArgumentException("foo");
  // [make a blah from a foo]
}

你可以让调用者看起来像这样:

Foo foo = GetFooFromUser();
try
{
    blah = MakeMeABlah(foo);
}
catch(...)
{
   // Tell user that input foo was invalid
}

那不太好。您的问题的解决方案是将IsValid变为公共方法:

Foo foo = GetFooFromUser();
if (!IsValid(foo))
   // Tell user that input foo was invalid
else
   blah =  MakeMeABlah(foo);

嘿,没有异常处理,的代价是必须两次调用IsValid 。如果验证便宜,谁在乎呢?如果验证成本很高,那么您可能希望进一步重构这个内容版本的MakeMeABlah,它不会在发布版本中重新进行检查。

答案 1 :(得分:1)

官方C#Design guidelines说要抛出异常并让用户界面层处理异常。

答案 2 :(得分:0)

如果曲线无效,为什么还要构建曲线?使用构建器模式,您可以公开仅构建有效Curve对象的功能,并允许UI在那里处理无效状态。

这是(我认为)Eric的建议的本质,在构造无效对象之前公开了一种验证状态的外部方法。

注意:一旦构建了有效的Curve对象,就可以删除可怕的if-creating布尔值“bool BaseCurveIsValid”。 :)