这个“模式”有名字吗?
”是否有一个名称,其中方法签名称为 TrySomething,例如 int.TryParse
、decimal.TryParse
等。
我想知道这个“模式 我的经常使用这种命名约定 - 他们不会返回值或抛出异常,而是调用一个方法 TryDoSomething ,如果在处理过程中捕获异常,它将通过输出参数返回。
编辑:我知道提供的示例不是 TryParse 方法的工作原理。这就是发布此内容的目的...我不知道该怎么称呼它。我同意它看起来更像是一种命名约定,而不是一种模式。感谢您的所有意见。
编辑:有趣...
考虑可能抛出异常的成员的 TryParse 模式常见场景的异常处理,避免与异常相关的性能问题。
要实现 TryParse 模式,您需要提供两种不同的方法来执行可能在常见情况下引发异常的操作。第一个方法 X 执行操作并在适当的时候抛出异常。第二种方法 TryX 不会抛出异常,而是返回一个指示成功或失败的布尔值。成功调用 TryX 返回的任何数据均使用 out(Visual Basic 中的 ByRef)参数返回。 Parse 和 TryParse 方法是此模式的示例。
I'm wondering if there is a name for this "pattern" where a method signature is called TrySomething, e.g. int.TryParse
, decimal.TryParse
, etc.
A coworker of mine uses this naming convention frequently -- rather than returning a value or throwing an exception, they will call a method TryDoSomething
and if an exception is caught during processing it gets returned via out param.
Edit: I understand the example privided is not how the TryParse methods work. That was the point of posting this... I wasn't sure what to call it. I agree it seems more like a naming convention and not a pattern. Thanks for all the input.
Edit: Interesting...
Consider the TryParse pattern for members that may throw exceptions in common scenarios to avoid performance problems related to exceptions.
To implement The TryParse pattern, you provide two different methods for performing an operation that can throw exceptions in common scenarios. The first method, X, does the operation and throws the exception when appropriate. The second method, TryX, does not throw the exception, but instead returns a Boolean value indicating success or failure. Any data returned by a successful call to TryX is returned using an out (ByRef in Visual Basic) parameter. The Parse and TryParse methods are examples of this pattern.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
我可能会称之为错误隐藏模式。当您的代码通常会产生异常并用布尔值提前终止时,您可以从创建
TryX
中受益。如果您查看框架提供的方法,您会注意到TryX
变体存在,只要它不平凡或容易出错(或者应该在框架中经常这样做)来编写您自己的IsValidX
方法。如果必须捕获异常,则将其包装在方法中是没有意义的。你所做的只是让调试输入问题变得更加困难。用户可能只能看到失败方法的副作用,而不是通过良好的堆栈跟踪来追踪输入失败。更糟糕的是,在调试手头的问题时,开发人员可能必须重新创建钝的程序状态才能实现故障模式。
基本上,如果您先验知道某个操作会因异常而失败,那么提供伴随的
TryX
操作是合乎逻辑且正确的。这就是所谓的测试者-执行者模式。对操作的事后分析不是测试者-执行者,而只是简单的异常处理。I would likely call that the Error Hiding Pattern. You benefit from creating a
TryX
when you have code that would usually produce an exception that instead cuts out early with a boolean. If you look at the methods provided by the framework you'll notice theTryX
variants exist whenever it would be non-trivial or error-prone (or done so often it should be in the framework) to write your ownIsValidX
method.If you have to catch an exception, there is no sense wrapping this in a method. All you are doing is making it harder to debug input problems. Instead of having a nice stack trace to follow to trace down an input failure, the user may only see side effects of the failed method. Worse still, when debugging the issue at hand the developer potentially has to recreate obtuse program state in order to effect the failure mode.
Basically, if a priori you know an operation will fail with an exception, it is logical and proper to provide a companion
TryX
operation. This is the so-called Tester-Doer pattern. Post hoc analysis of an operation is not Tester-Doer, but rather just simple Exception Handling.在这篇关于 TryParse 的文章中,他们称之为测试者-执行者模式。
In this post about TryParse they call is the Tester-Doer pattern.
首先,如果您的描述是准确的,那么 int.TryParse 及其兄弟姐妹根本就不是这样工作的。
我承认,在我看来,这些方法略有缺陷,因为它们没有向调用者传达解析失败的原因,而只是告诉调用者它失败了。在这方面,我很乐意看到更好的方法来处理这个问题。
事实上,在我看来,更好的方法是我在第三方库中看到的,我不记得了,但基本上他们有各种自定义类型,其中有这样一对 Parse/TryParse 方法,并且他们做了以下:
out
参数同样,在我看来,这里的主要问题是它不可扩展。如果我想使用他们的系统和类型,并添加我自己的原因,我无法做到这一点,但它的某些变体可以轻松处理这个问题。
无论如何,int.TryParse 方法在内部根本不会引发任何异常。相反,他们会进行实际解析字符串的动作,如果他们遇到无法处理的东西,他们只会返回 false,就是这样,在游戏中没有例外。
异常处理比没有异常的替代方法稍微昂贵,这就是为什么一些此类核心方法针对性能进行了优化。
这就是为什么在我的评论中,我称您的模式(如果准确)是愚蠢的,因为您将异常处理与输出参数结合在一起。检索到该异常后,您可以对它做什么?扔掉它?然后你又回到了第一个方块。
我会认真审视你的模式并尝试改变它。
当然,所有这一切都取决于您对它的描述是否准确的假设。
First of all, if your description is accurate, that's not how int.TryParse and its siblings work at all.
I'll admit, those methods are slightly broken, in my opinion, since they don't convey the reason for the parsing failure to the caller, only that it failed. In this respect, I'd love to see a better way to handle this.
In fact, a better way, again in my opinion, was something I saw in a third party library which I don't remember, but basically they had various custom types which had such a Parse/TryParse pair of methods, and they did the following:
out
parameterAgain, the main problem here, in my opinion, was that it wasn't extensible. If I wanted to use their system, and types, and add a reason of my own, I couldn't do that, but some variants of that would easily handle this.
In any case, the int.TryParse methods doesn't internally throw any exceptions at all. Instead they go through the motions of actually parsing the string, and if they encounter something they can't cope with, they simply return false, that's it, no exceptions in play.
Exception handling is slightly more expensive than the alternative without exceptions, which is why some such core methods are optimized for performance.
That's why in my comment I called your pattern, if accurate, stupid, because you have combined exception handling with the out parameters. And what can you do with that exception once you've retrieved it? throw it? Then you're back at square one.
I would seriously look at your pattern there and try to change it.
Of course, all this hinges on the assumption that your description of it is accurate.
您可以将其称为
ExceptionSafeBridge
。它引导您从异常世界进入错误代码世界。但我不认为这是官方的。当您需要在 C 代码和托管代码之间进行桥接时,这种模式很常见。
You could call it a
ExceptionSafeBridge
. It leads you from the exception world to the error-code world. But I don't think it's official.This pattern is common when you need to bridge between e.g. C code and managed code.
我称之为“希望我有
Option
”模式(这类似于“希望我有Either
”模式 - 想象一下在哪里E:例外)。TryXYZ(在上面的示例中)使用布尔结果和
out
参数来模拟 Option。 (对于值类型,在这种情况下它可能是Nullable
——我怀疑int.TryParse
和朋友的情况并非如此,部分原因是 Nullable 出现得晚得多。网)。通过out
返回异常更类似于 Either。在 C# 中,我不建议捕获异常只是为了将它们传递给一般的
out
参数(这个“规则”可能与支持可区分联合和模式匹配的语言不同)——我尝试1)“正确”地处理它,无论它是如何定义的,在特定情况中很可能是out
;或者 2) 让它过去,以便调用者可以尝试相同的操作。(正如其他人指出的那样,这更像是一种约定)。
快乐编码。
I call it the "Wish I had
Option<T>
" Pattern (which is similar to the "Wish I hadEither<T,E>
" Pattern -- imagine where E : Exception).TryXYZ (in the above examples) simulates Option with using a boolean result and
out
paramter. (For value types it could beNullable<T>
in this case -- I suspect it is not like this forint.TryParse
and friends partially because Nullable's came much later to .NET). The returning the exception viaout
more closely resembles Either.In C# I would not recommend catching exceptions just to pass them to
out
parameters in general though (this "rule" may be different with a language that has support for discriminated unions and pattern matching) -- I try to 1) deal with it "correctly", however that is defined, which very well may beout
in particular circumstances; or 2) let it go so the caller can try the same.(As others have pointed out, this is more of a convention).
Happy coding.
设计模式通常指的是与语言无关的一般思想,所以不,这不是模式。这可能是一个习语,但很可能只是一个命名约定,正如亚伦在评论中正确提到的那样。
A design patters in usually referred to a general idea which is language-agnostic, so no, this isn't a pattern. It may be an idiom, but most likely it's just a naming convention, as Aaron rightly mentioned in a comment.
是的。这称为测试者-执行者模式。
Yep. It's called the Tester-Doer pattern.
如果在 tryparse 期间发生问题,即
,那么您不会通过 out 参数捕获异常,out 值为 0, false 作为布尔值返回。
最好的办法是使用“is”或“as”代替。
不过,我不会真正将您描述的方法称为模式......只是一种编码实践(不是最好的实践)。
as的例子:
上面的运行时比try/catch效率高很多。
如果您在 as 不可用时使用“is”(“as”不适用于所有类型),请确保不要通过实现 as with is 来添加冗余...仅使用其中之一。
if an issue occurs during tryparse i.e.
Then you wouldnt have an exception caught via out param, value 0 for out, false returned as the boolean value.
Best bet is to use "is" or "as" instead.
I wouldn't really call the approach you describe a pattern though... Just a coding practice (not the best one).
Example of as:
The above is much more efficient at runtime than try / catch.
If you use "is" when as is not available to you ("as" not usable on all types), be sure not to add redundancy by implementing as WITH is... only make use of one or the other.
TLDR:
Microsoft 将其称为 TryParse 模式。
长答案
Microsoft 将此称为“TryParse”模式。并且还有一个对此已有的讨论。
我的第一个想法是这很懒。如果Tester-Doer是检查然后执行,在我看来,执行然后测试应该称为Doer-Tester。我不知道为什么“解析”是这种模式的唯一可能的应用。
推测
但后来我想这也许是故意的。到目前为止,我正在努力寻找许多其他 TryX 方法。因此,有人可能认为此模式的应用受到限制,并且可能是一种反模式。
也就是说,可能已经确定忘记对这些 try 方法的测试并不是“成功的深渊”,并且不应该有任何代码可能无一例外地不执行任何操作。
这仍然留下了为什么“解析”是例外的谜团——也许它是被继承下来的。
TLDR:
Microsoft calls it the TryParse pattern.
Long Answer
Microsoft refers to this as the "TryParse" pattern. And there is also a discussion on this already on SO.
My first thought of this was that this was lazy. If Tester-Doer is to check and then execute, it seems to me that execute and then test should be called Doer-Tester. I don't know why "Parse" is the only possible application of this pattern.
Conjecture
But then I thought maybe this is on purpose. So far, I'm struggling to find many additional TryX methods. And so it's possible that someone made the decision that the applications of this pattern are limited and possibly an anti-pattern.
That said, it may have been determined that forgetting the test on these try methods is not "pit of success" and there shouldn't be code that potentially does nothing without exception.
That still leaves the mystery of why "parsing" is the exception - maybe it was grandfathered in.