C# 处理属性中的异常';s设置/获取

C# 处理属性中的异常';s设置/获取,c#,exception-handling,C#,Exception Handling,在下面的示例代码中,我获取一个字符串列表,并将它们连接到一个分隔字符串。当我使用带有空列表的setter时,就会出现问题。ToString方法抛出ArgumentOutOfRangeException,因为第二个参数是-1 这样的条件(getter/setter中抛出的异常)应该如何处理? 我不喜欢setter抛出异常的事实,因为调用方不知道类的内部结构,因此不必处理(甚至不知道如何处理)异常。捕获getter/setter中的所有异常并安静地处理它们听起来也不是个好主意,因为调用方不会知道ge

在下面的示例代码中,我获取一个字符串列表,并将它们连接到一个分隔字符串。当我使用带有空列表的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);
   }
}
//我意识到这不是最好的代码,但我想给出一个示例
//来证明我的问题。
私有字符串字符串变量;
常量字符串分隔符=“,”;
公共IList字符串列表
{
设置
{
StringBuilder StringBuilder=新的StringBuilder();
foreach(值中的字符串条目)
{
stringBuilder.Append(条目);
追加(分隔符);
}
字符串变量=stringBuilder.ToString(0,stringBuilder.Length-1);
}
}

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

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



请注意:在像你发布的代码一样的情况下,我也会考虑把这个方法变成一个属性而不是一个属性。您在这个属性设置程序中做了很多“工作”,这有点出乎意料。通过将此设置为一种方法,您将向用户提供一条线索,表明此属性中存在一些“处理”…

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

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



请注意:在像你发布的代码一样的情况下,我也会考虑把这个方法变成一个属性而不是一个属性。您在这个属性设置程序中做了很多“工作”,这有点出乎意料。通过将此作为一种方法,您将为用户提供一个线索,即此属性中存在一些“处理”…

我认为您的问题与最佳实践无关

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

 stringBuilder.ToString(0, stringBuilder.Length - 1);
通过不检查字符串长度,导致引发异常。如果长度为0,只需返回空字符串

如果我们是泛泛而谈,如果您有能力围绕常见问题、空集、格式不正确的数据进行编码,那么您应该尽最大努力保护用户免受不必要的错误


然而,有时突然/大声失败比默默失败要好。

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

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

 stringBuilder.ToString(0, stringBuilder.Length - 1);
通过不检查字符串长度,导致引发异常。如果长度为0,只需返回空字符串

如果我们是泛泛而谈,如果您有能力围绕常见问题、空集、格式不正确的数据进行编码,那么您应该尽最大努力保护用户免受不必要的错误


然而,有时突然/大声失败比默默失败要好。

首先,如果你能发现可能导致异常的人,请修复它,使异常不会发生。在这种情况下,在循环之前检查空列表,并适当设置变量

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


(*)只捕获您预期可能发生的事件——让意外事件向用户反映

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

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


(*)只捕获您预期可能发生的事件——让意外事件向用户反映

建议如果您可以在本地处理异常,那么您可以这样做:“不要使用异常来推卸责任”。在给定的示例中,这意味着检查一个空值,并在setter中适当地处理它。

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

+1我同意,如果您需要做足够的工作来关注捕获异常,那么它可能需要一个方法。将其变为方法的更好理由是:它似乎是一个“只写”属性。这很少是个好主意。@James:是的,虽然“真实”属性可能有一个getter,我想,因为OP关注get和set的这个问题。不知道这是不是福