什么时候应该在C#方法名称中使用“ Try”?


180

我们正在与我们的同事讨论方法名称以“ Try”开头的含义。

有以下意见:

  • 当方法可以返回空值时,请使用“尝试”。
  • 该方法不会引发异常时,请使用“尝试”。

官方定义是什么?方法名称中的“尝试”是什么意思?是否有关于此的官方指南?


83
+1在功能名称中花了这么大心的人实际上正在寻找“下一个家伙”。不知道为什么要获得接近的票数(这是来自今晚投了很多票的人。)
Jonathon Reinhart

7
@JonathonReinhart之所以获得票数很高,是因为“按照目前的情况,这个问题并不适合我们的问答形式。我们希望答案能得到事实,参考或特定专业知识的支持,但是这个问题很可能会引起辩论,争论。 ,投票或扩展讨论。”
Pranav Hosangadi

16
这里由微软,回答问题(见我的答案)的官方声明。那怎么不是事实?
Erik Schierboom

6
正如埃里克(Erik)所说,@ PranavHosangadi受到事实支持。另外,这里有很多经验丰富的C#开发人员,他们具有特定的专业知识来提供有效的答案。地狱,埃里克·利珀特(Eric Lippert)是首席C#语言架构师。我认为您可以称之为特定专业知识
Jonathon Reinhart 2013年

4
@ErikSchierboom这是MS准则,是事实。MS指南是正确使用的指南是主观且有争议的。
Servy 2013年

Answers:


148

这被称为TryParse模式,并且已由Microsoft记录。MSDN的“异常和性能官方页面显示

为在常见情况下可能引发异常的成员考虑TryParse模式,以避免与异常相关的性能问题。

因此,如果您的代码具有常规用例意味着可能会引发异常(例如解析int),则TryParse模式是有意义的。


2
记录此模式(搜索TryParse)的另一个有用链接blogs.msdn.com/b/kcwalina/archive/2005/03/16/396787.aspx
Vivek Maharajh 2013年

2
基本上,如果您具有TryParse方法,则应该具有一个在TryParse返回false时引发的Parse方法。相反,如果您具有Parse方法,则应考虑使用TryParse方法,当Parse抛出
异常

5
+1。除此之外,例外通常是针对“例外”情况的。如果您做的事情很容易失败,并且失败不是特别值得注意,那么使用这种模式比尝试/捕获更为惯用
Adam Robinson

这样的模式真的需要Microsoft的指导吗?似乎相当基本的东西。
戴夫·劳伦斯

19
基本内容,但这并不意味着准则没有用。如果您对平台的了解不够充分,那么正确掌握基本内容可能会非常困难。
Erik Schierboom 2013年

119

(已更正)有官方指南,如Erik所建议。

当我看到TrySomething方法时,我认为是

  • 不扔
  • 退货 bool
  • 如果我期望值,则通过'out'参数返回
  • Something一种方法可以让我自己处理任何异常。(编辑,杰西·韦伯建议)

4
更正-具有官方指南。请参阅Erik的答案。
nothrow

8
+1但我也有第4个期望:如果有一种TryFoo方法,将会有一个类似的Foo方法让我自己处理任何``异常。这些方法的签名可能会有所不同,因此它们的用法在没有其他代码更改的情况下是不能互换的。
Jesse Webb

1
@JesseWebb,感谢您指出这一点。如果您不介意,我已将您的评论添加到我的答案中。
nothrow 2013年

1
在我看来,“不扔”过于笼统。例如,如果Int32.TryParse(String,NumberStyles,IFormatProvider,Int32)不喜欢style参数,则会引发ArgumentException。
Jirka Hanika

我同意“不抛出”可能被认为过于笼统,但我相信其意图是传达它不是由于执行而不是参数值的结果而抛出。
ConfusingBoat

8

我认为您应该try继续使用。一个方法是否返回某个值都没关系。

情况1:如果恢复正常,则可以采取某种方式。

情况2:如果不返回:就可以了;您可以采用其他方式进行。

如果您希望该方法的输出有一些值,请使用out参数。

int value
if (dictionary.TryGetValue("key", out value))
{
    // Proceed in some way
}
else
{
    // Proceed in some other way
}

6

当您想表明方法调用可能产生无效结果的事实时,必须在方法名称中使用“ Try”。顺便说一句,遵循.NET标准,它不是引发异常的函数,而是从程序角度返回某些VALIDNON_VALID值的函数。

最后,您决定在小组中使用的所有有关命名约定的内容。


5

try如果满足以下条件,请确保在您的方法名中包括:

  • 你不会抛出任何异常
  • 您的方法具有以下签名: bool TrySomething(input, out yourReturn)

因此,基本上,如果我们使用try-methods,我们只会得到一个布尔结果。

因此,以下代码不会引发任何异常:

string input = "blabla";
int number;
if (int.TryParse(input, out number))
{
// wooohooo we got an int!
} else
{
//dooh!
}

而此代码可以(并且在这种情况下)会引发异常:

string input = "blabla";
int number;
try
{
     number = int.Parse(input); //throws an exception
}
catch (Exception)
{
     //dooh!
}

使用Try方法是一种更安全,更具防御性的编码方式。另外,如果代码片段不是整数,则代码片段2会提高执行性能。


int number = int.Parse(input);如果您希望它在此情况下更有意义,则应阅读代码段2 。
皮埃尔·阿诺

@PierreArnaud谢谢,改变了它!
Fabian Bigler 2013年

int number;在try块和number = ...赋值之前,您仍然缺少声明。
皮埃尔·阿诺

@PierreArnaud谢谢,我现在也添加了“ int number”。
Fabian Bigler 2013年

请注意,如果该异常与正在执行的直接操作(例如,TryLoadFile(path, out file)哇声)在RAM 之外有点无关,您仍然可能会抛出异常。因此,呼叫者不会期望路径错误或访问被拒绝而产生任何错误,但会因怪异的事情而出错,这也会出错。并记录下来。
路加·普普利特

0

鲍勃叔叔在他的“ 清洁代码”一书中给出了下面的例子。每当我们期望抛出异常时,我们都可以使用Try方法名称的前缀:

public void sendShutDown()
{
    try{
        tryToShutDown();
    } catch (DeviceShutDownError e) {
        logger.log(e);            
    }
}

然后(适应):

private void tryToShutDown()
{
    //some code with no error handling, but
    //something might go wrong here
}

tryToShutDown方法不会进行任何错误处理,因为这是该sendShutDown方法的责任。

TryParseMicrosoft 的模式违反了明确的代码准则,该准则说我们应避免使用输出参数。

如果我们不开发新版本的C#,则不必遵守所有Microsoft准则。有时它们不是最好的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.