我有几个类似的方法,说如。CalculatePoint(...)和CalculateListOfPoints(...).有时,他们可能不成功,并需要表明这样的呼叫者。为CalculateListOfPoints,返回一个通用名单,我可以返回的一个空的名单,并要求呼叫者来检查;但是点是一个值的类型和所以我不能返回空在那里。

理想的是我会喜欢的方法,以"看"类似;一个解决办法是将它们定义为

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

或者返回这一点?为CalculatePoint,并回null,表示失败。这将意味着具有投回到非空类型不过,这似乎过多。

另一个途径将是返回的布尔boSuccess,结果(点或列表)作为一个'在'参数,并呼吁他们TryToCalculatePoint或东西...

什么是最好的做法吗?

编辑:我不想使用例外流的控制!失败有时是预期。

有帮助吗?

解决方案

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

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

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

其他提示

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

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

另一种选择是抛出异常。但是,您通常只想在“例外情况”中抛出异常。

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

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

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

如果我提供了TrySomething方法,我还会提供一个Something方法,在发生故障时抛出异常。然后由打电话者决定。

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

您的原始代码:
public Point CalculatePoint(... out Boolean boSuccess);
public List CalculateListOfPoints(... out Boolean boSuccess);

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

基本上你将成功/失败作为回报值。

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

  1. 当返回类型是一个值类型,如Point时,使用C#的Nullable特性并返回一个Point? (又名Nullable),这样你仍然可以在失败时返回null
  2. 发生故障时抛出异常。关于什么是和不是“例外”的整个论点/讨论。这是一个有争议的问题,它是你的API,你决定什么是特殊行为。
  3. 采用类似于Microsoft在Int32等基本类型中实现的模型,提供一个CalculatePoint和TryCalculatePoint(int32.Parse和int32.TryParse)并且有一个throw和一个返回bool。
  4. 从具有两个属性bool Success和GenericType Value的方法返回一个通用结构。
  5. 取决于场景,我倾向于使用返回null或抛出异常的组合,因为它们看起来“最干净”。对我而言,最适合我工作的公司的现有代码库。所以我个人的最佳实践是方法1和方法2。

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

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

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

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

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

public static readonly Point Empty

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

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

Maybe类看起来像这样:

/// <summary>
/// Represents the return value from an operation that might fail
/// </summary>
/// <typeparam name="T"></typeparam>
public struct Maybe<T>
{
    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; 
            }
    }
}

我认为最佳实践是返回值意味着成功,并且例外表示失败。

我认为您提供的示例中没有理由不使用例外情况

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

// 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的解析方法,但我认为我不喜欢它。

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

在大多数情况下,当您不想要例外时,尽可能返回null。

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

你不想被人投掷的例外情况时,有些预期发生的事情,如@凯文所说的例外是用于特殊情况下。

你应该返回的东西,预计对'失效的',一般空是我的选择不好的回报。

该文件对你的方法应该提前通知用户的期望是什么时数据 不计算.

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

嗯,有点,你可以送回去一点。空作为回报价值的失败的情况下。现在,所有这真的不会是返回的一点0为X和Y的价值,因此,如果这可以是一个有效的返回价值,我要远离这,但是如果你的方法将永远不会返回(0,0)点,然后可以使用。

抱歉,我只记得Nullable类型,你应该看一下。我不太确定开销是多少。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top