代码之家  ›  专栏  ›  技术社区  ›  brainimus user417509

处理属性的set/get中的异常

  •  1
  • brainimus user417509  · 技术社区  · 14 年前

    在下面的示例代码中,我将获取一个字符串列表,并将它们连接到一个带分隔符的字符串。当我使用带有空列表的setter时,就会出现问题。ToString方法引发ArgumentOutOfRangeException,因为第二个参数是-1。

    如何处理这种情况(getter/setter中抛出的异常)?

    我不喜欢setter抛出异常的事实,因为调用者不知道类的内部,因此不必处理(甚至不知道如何处理)异常。捕获getter/setter中的所有异常并悄悄地处理它们,这听起来也是一个坏主意,因为调用方不会知道getter/setter失败。

    //I realize that this isn't the best code but I wanted to produce an example
    //to demonstrate my question.
    private string theStringVariable;
    const string DELIMITER = ",";
    
    public IList<string> StringList
    {
       set
       {
          StringBuilder stringBuilder = new StringBuilder();
          foreach(string entry in value)
          {
             stringBuilder.Append(entry);
             stringBuilder.Append(DELIMITER);
          }
          theStringVariable = stringBuilder.ToString(0, stringBuilder.Length - 1);
       }
    }
    
    4 回复  |  直到 14 年前
        1
  •  6
  •   Reed Copsey    14 年前

    您应该检查潜在的、常见的错误条件,并在前面抛出自己的异常(在StringBuilder错误之前),并显示一条有意义的错误消息。

    在您的例子中,如果使用空字符串列表调用setter,您很可能希望使用某种形式的argumentexception。这里的关键是,您的异常可以说“参数包含一个空集合”,而不是“索引越界”,这将使调用者立即理解为什么他们的调用中存在“真正的”问题。


    附带说明:在像您发布的代码这样的情况下,我也会考虑将其作为方法而不是属性。您在这个属性设置器中做了相当多的“工作”,这会有点出乎意料。通过将此方法设置为一个方法,您将向用户提供一个线索,表明在该属性中发生了一些“处理”…

        2
  •  1
  •   Nix    14 年前

    我认为你的问题不涉及最佳实践。

    在您的案例中,您需要注意的最佳实践是

     stringBuilder.ToString(0, stringBuilder.Length - 1);
    

    不检查字符串长度会引发异常。如果长度为0,则返回空字符串。

    如果我们谈论的是一般性的问题,如果您能够围绕常见问题、空集、格式错误的数据进行编码,那么您应该尽最大努力避免用户出现不必要的错误。

    然而*有时最好是突然/大声失败,然后是默默失败。

        3
  •  0
  •   James Curran    14 年前

    首先,如果你能发现可能导致异常的人——修复它,这样异常就不会发生。在这种情况下,在循环之前检查一个空列表,并适当地设置varaible。

    否则,捕获异常(您期望的异常可能会发生(*),抛出一个新的更合适的异常(原始异常作为内部异常)

    (*)只捕获您期望的可能发生的情况——让意外的情况向用户冒泡。

        4
  •  0
  •   rtalbot    14 年前

    Code Complete 如果您可以在本地处理异常,建议您这样做:“不要使用异常来传递责任”。在给出的示例中,这意味着检查空值并在setter中适当地处理它。