为什么哈文';解析帮助程序变得更容易使用

本文关键字:易使用 帮助程序 哈文 为什么 | 更新日期: 2023-09-27 17:57:37

给定。NET团队表示(我会找到消息来源…),他们对基元类型的解析方法(例如Int32.TryParse(String s, out Int32 result))的设计感到遗憾,为什么没有用更明显、更适合客户端的变体来更新这些方法?

框架版本:

Int32? numValue;
Int32 placeHolder;
if (! Int32.TryParse("not a number", out placeHolder))
    numValue = 10;

改进版本:

var numValue = Int32.Parse("not a number", 10);

改进解析方法的签名是:

public static Int32? Parse(String s, Int32? defaultValue = null);

它可能有一个天真的实现:

public static Int32? Parse(String s, Int32? defaultValue = null) {
    Int32 temp;
    return ! Int32.TryParse(s, out temp)
        ? defaultValue
        : temp;
}

为什么哈文';解析帮助程序变得更容易使用

我不确定会有一个明确的答案,除非BCL团队的人有故事要讲。

一些考虑因素可能是:

  1. 更改方法将构成对现有的代码库几乎没有(如果有的话)收益。一些可能会辩称,由于以下原因,这将是一种损害
  2. Nullable types框包装的包装导致(轻微)性能下降的基础值即使您希望解析成功,但不希望可以为null的类型
  3. 如果您知道您的输入被认为是有效的,那么Parse方法为输入的异常情况抛出异常无效。这通常更具表演性,因为我们没有额外的当我们不需要时的错误处理代码设计观点。如果你打算处理无效案件,这就是TryParse的作用
  4. int Parse(string, int? defaultValue)int Parse(string)之间的混淆,主要是关于它们的错误处理。注意我已经删除了第一个方法的可选部分,否则它会同时拥有两个方法是没有意义的(您永远无法调用您的方法而不显式传递null)。在这一点上当一个重载在而另一个没有。有几个例外对此,例如类型GetType但它们通常是罕见的,在这种情况下,它们使用显式命名的参数,指示其不会抛出异常
  5. TryParse设计的另一个好处是它非常漂亮通过其API来显式地处理通过/失败结果。相当地而不是指示失败的幻数/结果(null),则返回单独的真/假值。现在,一些机制可以做到这一点(例如String.IndexOf返回-1),因此如果这是好事还是坏事。根据您的实践,使用返回的true/false值可能更容易,或者使用神奇的null结果可能是。但他们决定我想不要搅乱两种方法的水域做着完全相同的事情,但签名/返回值略有不同
  6. 另一个考虑因素是可为null的值类型有多常见。是你真的在很多地方使用Int32?吗?还是只是为了错误/输入处理?根据我的经验,可为null的值大多是用于数据库I/O(即使在那时,也不经常)。唯一其他时间可能是来自不可信来源的输入仅用于初始接口;所有底层代码仍然针对不可为null的CCD_ 13键入。在这种情况下,你有两个方法,原始:

    int input;
    if (TryParse(someString, out input))
        DoSomethingValid(input); //valid! Do something
    else
        ErrorMessage()//not valid, error!
    

    或者你的建议:

    int? input = Parse(someString)
    if (input != null)
        DoSomethingValid(input.GetValueOrDefault())//valid! Do something
    else
        ErrorMessage()//not valid, error!
    

    请注意是多么相似。你的建议真的提供了如果说这件事有什么不同的话。还要注意的用法GetValueOrDefault(),这是实际上访问包装值的更快/更好的方法,如果您知道它不是null,但很少(在至少从我在互联网上看到的)它是在Value上使用的吗访问者。如果BCL添加/更改了Parse方法建议,我认为很多的人会不必要地打CCD_ 17接入器。

    我不能特别评论使用可为null值的情况显著地贯穿应用程序设计和/或其层,但根据我的经验,它们很少使用或应该很少使用(对我来说,这几乎是"字符串类型"数据级别的代码气味)

最终,我认为添加扩展方法(除了Linq)的原因中的部分是为了允许用户根据需要推出自己的API。在您的情况下,您可以轻松地添加一个扩展方法来获得您想要的语法:

public static Int32? Parse(this String s, Int32? defaultValue = null)
{
    Int32 temp;
    return !Int32.TryParse(s, out temp)
        ? defaultValue
        : temp;
}
string validString = "1";
int? parsed = validString.Parse(); //1
int? failParsed = "asdf".Parse(9); //9

团队通常倾向于维持现状,添加必须提供足够大的效益才能添加到系统中,团队还考虑API as-is中已经存在的解决方案。我建议,考虑到API的显著破坏性,考虑到扩展方法选项,改变它并不是一个大问题。

此签名:

public static Int32? Parse(String s, Int32? defaultValue = null);

将与现有的Parse(string s)重载冲突,因为如果未指定可选参数,则无法区分它们。现有的方法可能永远不会被更改或删除,因为这会破坏与现有代码的兼容性。

然而,可以创建不带out int value参数的TryParse过载:

public static int? TryParse(string s)

请注意,您不需要为默认值添加参数:您可以使用null合并运算符。

string s = ...
int value = int.TryParse(s) ?? 0;