为什么不';t t.TryParse返回一个可为null的<;T>;

本文关键字:null gt 一个 lt TryParse 返回 为什么不 | 更新日期: 2023-09-27 18:19:31

据我所知,int.TryParse(string, out int)存在于Framework 2.0之后。int?也是如此。

是否有理由使用out参数而不是返回int?,其中HasValue设置为falsetrue,具体取决于转换能力?

为什么不';t t.TryParse返回一个可为null的<;T>;

原因很简单,因为当int.TryParse添加到该语言时,Nullable<T>并不存在。

在Eric Lippert的这篇博客文章中,底部有一行字:

解决方案是编写自己的扩展方法版本的TryParse,就像当初中有可为null的值类型时一样

这清楚地表明在CCD_ 10的原始实现中不可使用可为null的类型。Eric Lippert是编写C#编译器的团队成员,所以我认为这是一个非常权威的来源。

我无法说出实际原因,但我看到了三个可能的原因:

1) 可为null的类型是在.NET 2.0中引入的,而自.NET 1.1以来,第一个TryParse方法就已经存在了。因此,当引入可为null的类型时,对这样的API更改为时已晚;并且新的类不会以不同的方式实现CCD_ 12,因为已经设置了模式。

2) 并非所有类型都可以与Nullable结构一起使用,只有值类型可以。但是,有些方法遵循Try*模式,必须返回引用类型。例如,一个字典可能完全合法地包含null作为一个项,因此它的TryGetValue方法需要一种额外的方式来表示没有找到关键字。

3) 按照Try*-方法的编写方式,可以编写如下代码:

int myValue;
if (int.TryParse("42", out myValue)) {
    // do something with myValue
}
    // do something else
}

现在,假设TryParse只返回了一个int?。您可以丢弃myValue变量并丢失结果:

if (int.TryParse("42").HasValue) {
    // do something with ... what? You didn't store the conversion result!
}
    // do something else
}

或者你可以添加一个可以为null的变量:

int? myValue = int.TryParse("42");
if (myValue.HasValue) {
    // do something with myValue.Value
}
    // do something else
}

这不再是当前版本的优势,相反,它需要在以后的一些实例中写入myValue.Value,否则一个简单的value就足够了。请注意,在许多情况下,需要有关if语句的操作是否成功的信息。

这里引用了Julie Lerman的博客(2004年):

我已经在三月份的预览版中使用了nullable,但还没有在五月份,当我将使用nullable<t>与当前选项进行比较时,我对当前的性能(但bcl团队计划进行重大改进!!)感到失望。例如,对于值类型:

myNullableInt.HasValue与(在VB中)进行比较是myInt < 0

或参考类型

myNullableThing.HasValue与"if not myThing=null"的比较

可为null的类型是,目前要慢得多。BCL团队中的一些人曾向我承诺,计划是使可为null的功能更具性能

我也得到了提示,在未来,以下将是可能的:

Nullable<T> Parse(string value); 
Nullable<Int32> i = Int32.Parse( some String );

并且将比TryParse更具性能。所以这也会很有趣。

认为一如既往,收益大于成本。

无论如何,在即将到来的C#vNext中,你可以做:

DateTime.TryParse(s, out var parsedDateTime);

将TryParse转换为一行。

另一个可能的原因:

目前形式的.NET和C#的泛型几乎没有发生:这是一个非常接近的决定,而且这个功能几乎没有进入Whidbey(VisualStudio2005)。在数据库上运行CLR代码等功能被赋予了更高的优先级。

最终,将采用泛型的擦除模型,就像Java一样,因为如果没有外部帮助,CLR团队永远不会追求VM中的泛型设计。

来源:http://blogs.msdn.com/b/dsyme/archive/2011/03/15/net-c-generics-history-some-photos-from-feb-1999.aspx

我的观点是:BCL中的大多数更改(或者至少那些与泛型不直接相关的更改)可能需要同时使用带有和不带有泛型的,以防该功能在最终RTM中被剪切。

当然,从调用客户端的角度来看,这也是有道理的:理想情况下,所有的消费语言(好吧,当时没有那么多)都可以使用它们,而out参数没有泛型那么前沿。

至于原因我们只能猜测,但一些可能的原因是:

赋值开销:一个装箱的值会在内置类型上产生一些(小的)性能开销。

没有实际收益:

int res;
if int.TryParse("one", out res) {
  //something
}

不比差多少

int? res = int.TryParse("one");
if (res.HasValue){
  int realres = res.Value
  //something
}