int.TryParse(string, out int)
。 同样也有 int?
。是否有理由使用
out
参数而不是返回一个 int?
,其中 HasValue
根据能否进行转换设置为 true
或 false
?int.TryParse
到语言中时,Nullable<T>
不存在。TryParse
时无法使用可空类型。 Eric Lippert曾经参与编写C#编译器的团队,所以我认为他是一个非常权威的来源。TryParse
方法已经存在于.NET 1.1中。因此,在可空类型被引入时,进行API更改为时已晚;并且新类不会以不同的方式实现TryParse
,因为模式已经被确定。Nullable
结构一起使用,只有值类型可以。但是,有些方法遵循Try*
模式,必须返回引用类型。例如,字典完全可以包含null
作为项,因此其TryGetValue
方法需要一种额外的方式来表示未找到键。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
语句。TryParse
方法。out
关键字有点不自然。out
也有它的用处。甚至 goto
偶尔也有它的用途。 - asawyer以下是Julie Lerman(2004年)博客上的一句话:
我假设像往常一样,收益大于成本。I have played with
nullable
in the March preview bits, but not yet in the May and disappointed with the current (but slated for serious improvement by the bcl team!!!) performance when I compared the usingnullable<t>
over current options. So for example with value types:comparing
myNullableInt.HasValue
to (in VB) ismyInt < 0
or with reference types
comparing
myNullableThing.HasValue
to “if not myThing=null
”the nullable type is currently much much slower. I have been promised by a few on the BCL team that the plan is to make the nullable MUCH more performant.
I have also been given the hint that in the future, the following will be possible:
Nullable<T> Parse(string value); Nullable<Int32> i = Int32.Parse( some String );
And will be more performant than
TryParse
. So that, too will be interesting.
DateTime.TryParse(s, out var parsedDateTime);
DateTime dt = DateTime.TryParse(s, out dt) ? dt : DateTime.MinValue;
- Tim Schmelter还有一个可能的原因:
.NET和C#的泛型几乎没有成型:它与Whidbey(Visual Studio 2005)的特性几乎没有进展。那时更重要的是像在数据库上运行CLR代码这样的功能。
...
最终,由于CLR团队不会追求一个内置VM的泛型设计而没有外部帮助,因此采用了Java一样的擦除模型。
我的观点是: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
}
int?
需要8个字节的栈空间;一个int
和一个bool
:需要8个字节的栈空间...但是:一个bool
和一个ref int
实际上可能需要12个字节的栈空间(在x64中);p 意思是:out
版本实际上需要更多的赋值操作,当然还有一些额外的解引用操作,在另一个版本中是不必要的。我的观点是:两者都有代价。 - Marc Gravellout
不是将值装箱吗? - krimog
ToNullableInt
的扩展方法,实现所需的行为。如果未来版本的C#原生支持此功能,我不会感到意外。 - Rob EpsteinNullable<int> result = int::TryParse(...)
。 - StephanmyInt
的情况下就能够使用int.TryParse(string, out int myInt)
。 - Avner Shahar-Kashtan.TryParse()
方法,他们会返回Nullable<T>
,但当时它不存在(或者至少不像现在这样好)。我会看看能否找到它。 - anaximander