何时使用 Cast 或 Convert

83

我很想知道将一个变量转换为int和使用Convert.ToInt32()的区别是什么。是否有一种方法比另一种更加高效?

此外,应该在哪种情况下使用每一个?目前,我更倾向于使用Convert,但我没有理由选择其中的任何一种。在我看来,它们都可以实现相同的目标。


5
我不同意将我的问题视为与这个问题完全相同的副本。这个问题询问何时使用强制转换或转换,下面的被接受的答案说明,“无论使用哪种方法都只是选择的问题。” 我的问题明确要求区分强制转换和使用 Convert.To() 的区别。因此,我的问题作为你的问题的补充。 - user5398447
9个回答

80

当变量类型为int时,使用Cast转换;当变量类型不是int但你希望它变成int类型时,使用Convert转换。

例如,当你知道变量o是一个整数时,可以这样写:int i = (int)o;

当"123"不是一个整数而是一个字符串表示的整数时,可以使用Convert.ToInt32("123")进行转换。


1
使用枚举类型时,这会产生什么影响? - Jonas Stawski

41

在另一个论坛上查看Cast和Convert之间的差异

答案

Convert.ToInt32(String, IFormatProvider)底层调用Int32.Parse(请参阅备注)。
因此,唯一的区别在于如果传递了空字符串,则返回0,而Int32.Parse会抛出ArgumentNullException
实际上,无论使用哪种方法都是个人选择。

个人而言,我都不使用它们,而倾向于使用TryParse函数(例如System.Int32.TryParse())。


更新

顶部链接已失效,请查看StackOverflow上这个答案


73
重要提示:我最近注意到的另一个区别是,“Cast”将1.63转换为1,而“Convert”将1.63转换为2。因此,基本上Convert会四舍五入并转换值,而Cast会在小数点后截断值。 - Abijeet Patro
有时候 TryParse 不可用。 - Shaun Luttin
3
紧凑框架缺少TryParse功能:http://stackoverflow.com/questions/22670260/does-the-net-compact-framework-have-the-tryparse-methods-where-is-the-document - Shaun Luttin
类型转换只能将封装在“对象类型”变量中的值转换为所指向值的类型,而转换操作不仅会取消封箱操作,还可以转换为任意类型。例如,object o = 1L; double d = (double)o; 将会失败,而 Convert.ToDouble(o) 则能正常工作。 - Domino
2
仅供@AbijeetPatro评论参考,引自Joseph Albahari和Ben Albahari的《C# 5.0 in a Nutshell》。版权所有2012 Joseph Albahari和Ben Albahari,978-1-449-32010-2。当您从浮点数转换为整数时,任何小数部分都将被截断;不执行四舍五入。静态类System.Convert提供了在各种数字类型之间转换时进行四舍五入的方法。 - Burak Karakuş
1
OP在哪里说他想要转换字符串?如果强制转换是一个选项,它就不能是一个字符串。 - Tim Schmelter

13

还有一个区别。"转换"总是进行溢出检查,而"强制转换"则可能取决于您的设置以及使用的 "checked" 或 "unchecked" 关键字。

更明确地说,请考虑以下代码:

int source = 260;
byte destination = (byte)source;

目的地将会在没有警告的情况下变为4。

但是:

int source = 260;
byte destination = Convert.ToByte(source);

会给你一个异常。


6

并非所有类型都支持转换,比如:

int i = 0;
decimal d = (decimal)i;

因为需要实现显式操作符,所以必须使用 explicit operator。但是.NET也提供了IConvertible interface,因此任何实现该接口的类型都可以转换为大多数框架内置类型。最后,Convert类可帮助操作实现IConvertible接口的类型。

4

强制类型转换只是告诉编译器该对象实际上是不同类型的实现,并且现在应将其视为新实现。而转换则表示它不继承要转换的内容,但有一种固定的方式可以进行转换。例如,假设我们将“16”转换为int。“16”是一个字符串,与int没有任何继承关系。但是,显然可以将“16”转换为int 16。


2

在这里我想提出一点建议,似乎有必要做一个概念上的区分。虽然我不是专家:

强制类型转换是改变代表类型。所以"32"、32L和32.0f之间进行强制类型转换似乎是合理的。C#不会自动支持"32",但大多数动态语言都会。因此我会使用(long)"32"或(String)32L。只要能用就用。我还有另一个规则——强制类型转换应该是可逆的。

转换不需要可逆,可以简单地创建一个全新的对象。

灰色地带是例如字符串"32xx"。可以认为当你将其转换时,它变成了32L(数字被解析直到无法解析为止)。Perl就是这样使用的。但这违反了我的可逆性要求。对于32.5f到32L也是同样的情况。几乎所有的语言,包括非常静态类型的语言都允许这种转换,但它也不符合可逆性规则。这是一个灰色地带,如果你允许"32"被转换,那么在编译时你就不知道它是否可能是"32xxx"。

还有一种区别可以做的是只用强制类型转换来进行"IsA"而不是"makeLookLikeA"。所以如果你知道一个字符串来自数据库但实际上在非正式模式中是一个整数,可以放心地使用强制类型转换(虽然在这种情况下C#希望你使用Convert)。同样的情况也适用于浮点数。但不能用于只是用强制类型转换来截断浮点数的情况。这种区别还考虑了向下转型和向上转型——对象始终是'IsA',但类型可能已经被概括为列表。


1

Convert.ToInt32有很多重载,可以接受例如字符串之类的参数。尝试将字符串强制转换为整数会导致编译错误。关键在于它们用于不同的情况。当你不确定要从哪种类型的对象进行转换时,Convert特别有用。


0

你应该使用Convert.ToInt32而不是强制转换的另一个原因是:

例如:

float a = 1.3f;
float b = 0.02f;
int c = (int)(a / b);
int d = Convert.ToInt32(a / b);`

结果是 c = 64,d = 65


这不是由于强制转换,而是由于转换规则。当你除以2个浮点数时,你会得到一个双精度值64.999999068677411,当转换为整数时,它只截取整数部分。但这将返回65:(int)(float)(a / b)),因为在浮点数中它恰好是65,而不是64.99(9)。小数也是一样的。相反,Convert会将结果四舍五入,因此它在这里返回65,但64.49将返回64。有趣的是,Intellisense说将其转换为浮点数是多余的,而没有它会返回64。 - Vitaly

0

string number = "123abc";

int num;

Int32.TryParse(number, out num); // 在此调用中没有抛出异常

Convert.ToInt32(number); // 在此调用中抛出了异常


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接