这个“模式”有名字吗?

时间:2011-03-31 19:42:36

标签: c# design-patterns

我想知道这个“模式”是否有名称,其中方法签名称为TrySomething,例如int.TryParsedecimal.TryParse

我的同事经常使用这种命名约定 - 而不是返回值或抛出异常,他们将调用方法TryDoSomething,如果在处理过程中捕获到异常,则会通过out param返回。 / p>

编辑:我理解私有的例子不是TryParse方法的工作原理。这就是张贴这个......我不知道该怎么称呼它。我同意它似乎更像是命名约定而不是模式。感谢您的所有投入。

修改:Interesting ...

考虑可能在常见场景中抛出异常的成员的TryParse模式,以避免与异常相关的性能问题。

  

要实现TryParse模式,您需要提供两种不同的方法来执行可在常见方案中引发异常的操作。第一个方法X执行操作并在适当时抛出异常。第二种方法TryX不会抛出异常,而是返回一个表示成功或失败的布尔值。使用out(Visual Basic中的ByRef)参数返回成功调用TryX返回的任何数据。 Parse和TryParse方法就是这种模式的例子。

8 个答案:

答案 0 :(得分:13)

我可能会称之为Error Hiding Pattern。当您拥有通常会产生异常的代码时,您可以从创建TryX中受益,而异常则会使用布尔值提前删除。如果你看看框架提供的方法,你会注意到TryX变体存在,只要它是非平凡的或容易出错的(或者通常它应该在框架中完成)来编写自己的IsValidX变体{ {1}}方法。

如果你必须捕获异常,那么在方法中包装它是没有意义的。您所做的只是使调试输入问题变得更加困难。用户可能只看到失败方法的副作用,而不是跟踪一个好的堆栈跟踪来追踪输入失败。更糟糕的是,在调试手头的问题时,开发人员可能必须重新创建钝的程序状态才能实现故障模式。

基本上,如果先验您知道操作将因异常而失败,那么提供伴随TryX操作是合乎逻辑的。这就是所谓的 Tester-Doer 模式。对操作的事后分析不是 Tester-Doer ,而只是简单的异常处理

答案 1 :(得分:7)

他们称之为<In this post about TryParse的是Tester-Doer模式。

答案 2 :(得分:6)

首先,如果你的描述是准确的,那不是int.TryParse及其兄弟姐妹的工作方式。

我承认,在我看来,这些方法稍有破坏,因为它们没有向调用者传达解析失败的原因,只是失败了。在这方面,我希望看到一个更好的方法来解决这个问题。

事实上,在我看来,更好的方式是我在第三方库中看到的一些我不记得的东西,但基本上他们有各种自定义类型,这些类型具有这样的Parse / TryParse方法,并且他们做了以下事情:

  1. 定义一个通用结构,其中包含通过解析字符串获得的值以及传递解析结果的枚举类型值
  2. 所有TryParse方法都返回此结构,并且没有out参数
  3. Parse方法简单地称为TryParse方法,然后将该枚举的各种非成功结果转换为适当的异常
  4. 同样,在我看来,这里的主要问题是它不可扩展。如果我想使用他们的系统和类型,并添加我自己的原因,我不能这样做,但是一些变体很容易处理这个。

    在任何情况下,int.TryParse方法都不会在内部抛出任何异常。相反,他们经历了实际解析字符串的动作,如果他们遇到了他们无法应付的事情,他们只会返回虚假,就是这样,没有例外。

    异常处理比没有异常的替代方案略贵,这就是为什么一些这样的核心方法针对性能进行了优化的原因。

    这就是为什么在我的评论中我调用了你的模式,如果准确,愚蠢,因为你将异常处理与out参数结合起来。一旦你检索到它,你会怎么做?丢它?然后你又回到了第一个方向。

    我会认真看看你的模式并尝试改变它。

    当然,所有这一切都取决于您对它的描述是否准确的假设。

答案 3 :(得分:4)

我称之为“希望我有Option<T>”模式(类似于“希望我有Either<T,E>”模式 - 想象一下E:例外情况。)

TryXYZ(在上面的例子中)使用布尔结果和out参数模拟Option。 (对于值类型,在这种情况下它可能是Nullable<T> - 我怀疑它对于int.TryParse和朋友来说不是这样的,因为Nullable在很晚才到了.NET)。通过out返回异常更接近于Either。

在C#中,我不建议捕获异常只是为了将它们传递给out参数(尽管这个“规则”可能与支持有区别的联合和模式匹配的语言不同) - 我尝试1)“正确”地处理它,但是这是定义的,在特定情况下可能可能<{1}} ;或者2)放手让呼叫者也可以尝试。

(正如其他人所指出的,这更像是一种惯例)。

快乐的编码。

答案 4 :(得分:3)

您可以将其称为ExceptionSafeBridge。它引导您从异常世界到错误代码世界。但我不认为这是正式的。

这种模式,当你需要在例如C代码和托管代码。

答案 5 :(得分:1)

设计模式通常指的是与语言无关的一般概念,所以不,这不是一种模式。它可能是一个成语,但很可能它只是一个命名惯例,正如Aaron在评论中正确提到的那样。

答案 6 :(得分:1)

是的。它被称为Tester-Doer模式。

答案 7 :(得分:0)

如果在tryparse期间出现问题,即

 int val;
        if(int.TryParse("2", out val))
        {
            //do work with val
        }

然后你不会通过输出param捕获异常,值0输出为out,false返回为布尔值。

最好的办法是改为使用“是”或“as”。

我不会真的称之为你描述模式的方法......只是编码练习(不是最好的)。

as:

的例子
private void SetObj(object obj)
{
    int thisInt = obj as int;
    if(thisInt != null)
    {
       //do work
    }
    else
    {
       //handle issue
    }

}

以上在运行时比try / catch更有效。

如果您使用“is”时(“as”不可用于所有类型),请确保不要通过实现添加冗余,因为WITH只是使用其中一个。