Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么避风港';解析助手是否变得更容易使用?_C#_Parsing_Language Design_Nullable_Deprecated - Fatal编程技术网

C# 为什么避风港';解析助手是否变得更容易使用?

C# 为什么避风港';解析助手是否变得更容易使用?,c#,parsing,language-design,nullable,deprecated,C#,Parsing,Language Design,Nullable,Deprecated,鉴于.NET团队已经声明(我会找到一个来源…),他们对原语类型的解析方法的设计感到遗憾(例如),为什么没有用一个更明显的、对客户端友好的变体来更新这些方法 框架版本: Int32? numValue; Int32 placeHolder; if (! Int32.TryParse("not a number", out placeHolder)) numValue = 10; var numValue = Int32.Parse("not a number", 10); 改进版: I

鉴于.NET团队已经声明(我会找到一个来源…),他们对原语类型的解析方法的设计感到遗憾(例如),为什么没有用一个更明显的、对客户端友好的变体来更新这些方法

框架版本:

Int32? numValue;
Int32 placeHolder;
if (! Int32.TryParse("not a number", out placeHolder))
    numValue = 10;
var numValue = Int32.Parse("not a number", 10);
改进版:

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;
}
此签名:

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

但是,可以创建
TryParse
的重载,该重载不带
out int值
参数:

public static int? TryParse(string s)
请注意,您不需要为默认值添加参数:您可以改用null合并运算符

string s = ...
int value = int.TryParse(s) ?? 0;
此签名:

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

但是,可以创建
TryParse
的重载,该重载不带
out int值
参数:

public static int? TryParse(string s)
请注意,您不需要为默认值添加参数:您可以改用null合并运算符

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

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

一些考虑可能是:

  • 改变这些方法将构成一个巨大的突破性改变 现有的代码库几乎没有(如果有争议的话)收益。一些 可能会争辩说,出于以下原因,这将是一种损害
  • 可为空的类型框包装了导致(轻微)性能损失的基础值 即使您希望解析成功并且不希望 还是可以为空的类型
  • 如果您知道您的输入应该是有效的,那么 方法为输入 这是无效的。这通常更有效,因为我们没有额外的 错误处理代码时,我们不需要它,并期望从 设计观点。如果你打算处理这个无效的案子, 这就是
    TryParse
    的作用
  • int解析(字符串,int?defaultValue)
    int之间的混淆
    解析(字符串)
    ,主要是关于它们的错误处理。通知 我已经删除了第一个方法的可选部分,否则它会 两种方法都使用没有意义(您永远无法调用 您的方法没有显式地传入
    null
    )。在这一点上,它 当一个重载在上引发异常时,会有点混乱 失败,而另一个没有。有几个例外 对此,例如 但它们通常很少见,在这种情况下,它们使用显式命名的参数,指示它将或不会引发异常
  • TryParse设计的另一个好处是它非常漂亮 通过API显式处理通过/失败结果。相当地 它返回一个表示失败的幻数/结果(
    null
    ) 单独的真/假值。现在,一些机制可以做到这一点 (
    String.IndexOf
    例如返回-1)因此如果 这是好事还是坏事。根据你的练习, 使用return
    true/false
    值可能更容易,或者使用 magic
    null
    结果可能是。但他们决定我想不要弄脏了 用两种方法做完全相同的事情,但是 签名/返回值略有不同
  • 另一个需要考虑的问题是可空值类型有多常见。是 你真的在很多地方使用
    Int32?
    ?还是仅仅是为了 错误/输入处理?根据我的经验,可空值通常是 用于数据库I/O(即使如此,也不经常)。唯一的 其他时间可能是来自不可信来源的输入,这将 仅适用于初始接口;所有的底层代码仍然是 根据不可为空的
    Int32
    键入。在这种情况下,你有两个 方法,原文:

    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()
    ,如果您知道它是非空的,但很少(至少 至少从我在互联网上看到的情况来看)它是在
    值上使用的
    存取器。如果BCL添加/更改了
    Parse
    方法 建议,我认为很多人会不必要地打击
    访问器

    我不能特别评论使用可空值的情况 在整个应用程序设计和/或其各层中, 但根据我的经验,它们很少使用或应该很少使用(对我来说,这几乎是一种“严格类型”数据级别的代码味道)

  • 最终,我相信添加扩展方法(除了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中已经存在的解决方法。我建议,考虑到扩展方法的选择,考虑到API的显著破坏性,更改API并不是一个大问题。

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

    一些考虑可能是: