如何表明方法不成功

我有几种类似的方法,例如。 CalculatePoint(…)和CalculateListOfPoints(…)。 有时候,它们可能不会成功,需要向呼叫者表明这一点。 对于返回通用List的CalculateListOfPoints,我可以返回一个空列表并要求调用者检查这个; 但是Point是一个值类型,所以我不能在那里返回null。

理想情况下,我希望这些方法“看起来”相似; 一种解决方案可能是将它们定义为

public Point CalculatePoint(... out Boolean boSuccess); public List CalculateListOfPoints(... out Boolean boSuccess); 

或者返回一个点? 对于CalculatePoint,并返回null以指示失败。 这意味着必须回归到非可空类型,这似乎是过度的。

另一种方法是返回布尔boSuccess,将结果(Point或List)作为’out’参数,并将它们称为TryToCalculatePoint或其他…

什么是最佳做法?

编辑:我不想使用Exceptions进行流量控制! 有时候会失败。

就个人而言,我想我会使用与TryParse()相同的想法:使用out参数输出实际值,并返回一个布尔值,指示调用是否成功

public bool CalculatePoint(... out Point result);

我不喜欢为“正常”行为使用exception(如果您希望该函数不适用于某些条目)。

他们为什么会失败? 如果是因为调用者所做的事情(即提供的参数),那么抛出ArgumentException是完全合适的。 一个避免exception的Try […]方法很好。

我认为提供引发exception的版本是一个好主意,因此,如果他们错了,那么期望他们将始终提供良好数据的呼叫者将收到适当强烈的消息(即exception)。

另一种方法是抛出exception。 但是,您通常只想在“例外情况”中抛出exception。

如果失败案例很常见(并非例外),那么您已经列出了两个选项。 编辑 :您的项目中可能有一个约定如何处理此类非特殊情况(无论是应该返回成功还是对象)。 如果没有现有的约定,那么我同意lucasbfr并建议你返回成功(这与TryParse(…)的设计方式一致)。

如果失败是出于特定原因,那么我认为可以返回null,或者bool并且有一个out参数。 但是,如果无论失败都返回null,那么我不推荐它。 exception提供了丰富的信息,包括为什么出现故障的原因,如果你回来的都是null,那么你怎么知道它是否因为数据错误,你的内存不足或其他一些奇怪的行为。

即使在.net中,TryParse也有一个Parse兄弟,所以如果你愿意,你可以获得exception。

如果我提供了TrySomething方法,我还会提供一个Something方法,在发生故障时抛出exception。 然后由呼叫者决定。

我使用的模型与MS使用的模型与各种类的TryParse方法相同。

你原来的代码:
public Point CalculatePoint(… out Boolean boSuccess);
public List CalculateListOfPoints(… out Boolean boSuccess);

会变成公共bool CalculatePoint(… out(或ref)Point CalculatedValue);
public bool CalculateListOfPoints(… out(或ref)List CalculatedValues);

基本上,您将成功/失败作为返回值。

总结一下,您可以采取以下几种方法:

  1. 当返回类型是一个值类型,如Point时,使用C#的Nullable特性并返回一个Point? (又名Nullable),这样你就可以在失败时返回null
  2. 发生故障时抛出exception。 关于什么是“特殊”和不是“特殊”的整个论点/讨论是一个有争议的问题,它是你的API,你决定什么是特殊行为。
  3. 采用类似于Microsoft在Int32等基类型中实现的模型,提供一个CalculatePoint和TryCalculatePoint(int32.Parse和int32.TryParse)并且有一个throw和一个返回bool。
  4. 从具有两个属性bool Success和GenericType Value的方法返回一个通用结构。

根据场景我倾向于使用返回null或抛出exception的组合,因为它们对我来说似乎“最干净”并且最适合我工作的公司的现有代码库。 所以我个人的最佳实践是方法1和方法2。

它主要取决于您的方法的行为及其用法。

如果失败是常见且非关键的,那么让您的方法返回一个指示其成功的布尔值,并使用out参数来传达结果。 查找哈希中的密钥,在没有数据可用时尝试读取非阻塞套接字上的数据,所有这些示例都属于该类别。

如果失败是意外的,则直接返回结果并传达exception错误。 以只读方式打开文件,连接到TCP服务器,是很好的选择。

有时两种方式都有意义……

返回Point.Empty 。 当您想要检查结构创建是否成功时,返回特殊字段是一种.NET设计模式。 尽可能避免输出参数。

 public static readonly Point Empty 

我正在尝试的模式是返回一个Maybe 。 它具有TryParse模式的语义,但与null-return-on-error模式具有类似的签名。

我还不确定这种或那种方式,但我提供它供你集体考虑。 它确实具有以下优点:在方法调用之前不需要定义变量以在方法的调用站点处保持out参数。 它还可以使用ErrorsMessages集合进行扩展,以指示失败的原因。

Maybe类看起来像这样:

 ///  /// Represents the return value from an operation that might fail ///  ///  public struct Maybe { T _value; bool _hasValue; public Maybe(T value) { _value = value; _hasValue = true; } public Maybe() { _hasValue = false; _value = default(T); } public bool Success { get { return _hasValue; } } public T Value { get { // could throw an exception if _hasValue is false return _value; } } } 

我会说最佳实践是返回值意味着成功,而exception意味着失败。

我认为您提供的示例中没有理由不在发生故障时使用exception 。

在某些情况下使用exception是一个坏主意(特别是在编写服务器时)。 你需要两种方法。 另请查看字典类,以了解您应该做什么。

 // NB: A bool is the return value. // This makes it possible to put this beast in if statements. public bool TryCalculatePoint(... out Point result) { } public Point CalculatePoint(...) { Point result; if(!TryCalculatePoint(... out result)) throw new BogusPointException(); return result; } 

两全其美!

bool TrySomething()至少是一种练习,适用于.net的解析方法,但我认为我不喜欢它。

抛出exception通常是一件好事,但它不应该用于您在许多正常情况下预期会发生的情况,并且它具有相关的性能成本。

在大多数情况下,如果不需要exception,则在可能的情况下返回null。

但是 – 你的方法有点过程 – 如何创建类似PointCalculator类的东西 – 将所需的数据作为构造函数中的参数? 然后在其上调用CalculatePoint,并通过属性访问结果(Point和for Success的单独属性)。

当预期发生某些事情时,你不希望抛出exception,因为@Kevin声明exception是针对例外情况。

你应该返回一些预期的’失败’,通常是我选择的不良回报。

您的方法的文档应该告知用户数​​据不计算时会发生什么。

我们曾经写过一个完整的框架,其中所有公共方法都返回true(成功执行)或false(发生错误)。 如果我们需要返回一个值,我们使用输出参数。 与流行的看法相反,这种编程方式实际上简化了我们的许多代码。

使用Point,您可以在发生故障时将Point.Empty作为返​​回值发回。 现在这一切真的是返回一个0和X值的点,所以如果它可以是一个有效的返回值,我会远离它,但如果你的方法永远不会返回(0,0)点,那么你可以使用它。

对不起,我只记得Nullable类型,你应该看看。 我不太确定开销是多少。