为什么T.TryParse不返回Nullable <t> </t>

时间:2014-08-27 11:19:56

标签: c# .net

据我所知,int.TryParse(string, out int)自Framework 2.0以来就存在。 int?也是如此。

是否有理由使用out参数而不是将int?设置为HasValue true false,具体取决于转换的能力?

5 个答案:

答案 0 :(得分:21)

我无法说出实际原因,但我认为有三个可能的原因:

1)Nullable types是在.NET 2.0中引入的,而first TryParse methods自.NET 1.1以来就已经出现了。因此,当引入可空类型时,这种API更改为时已晚; TryParse,因为模式已经设置好了。

2)并非所有类型都可以与Nullable structure一起使用,只有值类型可以。但是,Try*模式后面的方法必须返回引用类型。例如,字典可能完全合法地包含null作为项目,因此其TryGetValue method需要另外一种方式来表示未找到密钥。

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
}

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

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

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

答案 1 :(得分:21)

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

this blog post by Eric Lippert中,底部有一条线:

  

解决方案是编写自己的扩展方法版本的TryParse,就像在第一时间可用的可空值类型一样编写它

明确指出可以在TryParse的原始实现中使用可空类型。 Eric Lippert是编写C#编译器的团队,因此我认为这是一个非常权威的来源。

答案 2 :(得分:5)

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

  

我在3月的预览位中使用了nullable,但是在5月份还没有玩过,并且当我比较使用时,对当前(但是bcl团队的严重改进)的表现感到失望。 {1}}当前选项。例如,使用值类型:

     

nullable<t>与(在VB中)比较为myNullableInt.HasValue

     

或参考类型

     

myInt < 0与“myNullableThing.HasValue”进行比较

     

可空类型目前要慢得多。 BCL团队的一些人承诺承诺可以让可以自由的更高效率

     

我也得到了一个暗示,将来可能会有以下几点:

if not myThing=null
     

并且比Nullable<T> Parse(string value); Nullable<Int32> i = Int32.Parse( some String ); 更高效。所以,这也很有趣。

假设一如既往,好处超过了成本。

无论如何,在即将推出的C#vNext中,您可以这样做:

TryParse

将TryParse变成一个单线。

答案 3 :(得分:4)

另一个可能的原因:

  

当前形式的.NET和C#的泛型几乎没有发生:这是一个非常接近的调用,并且该功能几乎没有为Whidbey(Visual Studio 2005)做出决定。诸如在数据库上运行CLR代码等功能被赋予了更高的优先级。

     

...

     

最终,对于Java来说,将采用泛型的擦除模型,因为CLR团队在没有外部帮助的情况下永远不会追求虚拟机内的泛型设计。

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

我的观点是:BCL中的大多数更改(或者至少那些直接与泛型有关的更改)可能需要同时使用使用和不使用泛型,该特征在最终的RTM中被删除的情况。

当然,从主叫客户的角度来看,这也是有意义的:所有消费语言(好的,当时没有多少人)理想情况下能够使用它们 - 以及out个参数并不像普通人那样具有前沿性。

答案 4 :(得分:3)

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

分配开销:盒装值会比内置类型产生一些(小)性能开销。

没有真正的收获:

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

并不比

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