Convert.ToInt32和(int)有什么区别?

69
以下代码会抛出编译时错误,如下所示:
无法将类型 "string" 转换为 "int"。
string name = Session["name1"].ToString();
int i = (int)name;

以下代码编译并成功运行:

string name = Session["name1"].ToString();
int i = Convert.ToInt32(name);

我想知道:

  1. 第一段代码为什么会产生编译时错误?

  2. 这两段代码片段有何不同?


2
有趣。通常问题是Convert.ToInt32()和(Int32.ParseInt32.TryParse())之间有什么区别 :-) - Joey
2
第一种是显式转换,你在说name是一个int类型,并且从那时起应该被称为这样。 第二种将字符串转换为int类型,有效地解析它。 - Daniel Dawes
2
@DanielDawes 这有点误导人 - 在 C# 中,有效的强制转换确实会发生类型转换。例如,浮点数存储的位与强制转换为整数后得到的值存储的位是非常不同的。 - dcstraw
12个回答

83

(int)foo 简单地将变量 foo 强制转换为 Int32(在 C# 中使用 int)。这个操作是内置于 CLR 中的,需要变量 foo 是数字类型(例如 floatlong 等)。在这个意义上,它与 C 语言中的强制转换非常相似。

Convert.ToInt32 被设计为通用转换函数。它做的事情比仅仅进行类型强制转换要多得多;它可以从 任何 基本数据类型转换为 int(尤其是解析一个 string)。您可以在 MSDN 上看到该方法的完整重载列表

正如 Stefan Steiger一条评论中所提到的

此外,值得注意的是,在数值级别上,(int) foo 截断 foo(即 ifoo = Math.Floor(foo)),而 Convert.ToInt32(foo) 使用银行家舍入法(将 x.5 四舍五入到最接近的偶数,这意味着 ifoo = Math.Round(foo))。因此,结果不仅在实现上不同,而且在数值上也相同。


28
注意,就数字层面而言,将foo强制转换为整型 (int) foo 会将foo截断(即ifoo等于floor(foo)),而ToInt32(foo)则使用数学舍入(即将x.5四舍五入到最近的偶数整数,意味着ifoo=Math.Round(foo))。因此结果不仅在实现方式上有所不同,而且在数字上也不相同。 - Stefan Steiger
请在您的答案中包含@StefanSteiger有关四舍五入的注释。这可以拯救生命(: - Saro Taşciyan
1
另外值得注意的是:(int)UInt32.MaxValue为-1,而Convert.ToInt32(UInt32.MaxValue)会抛出OverflowException异常。 - jcox

18

(这一行涉及到一个被合并的问题) 你绝不应该使用 (int)someString - 那永远都不会起作用(编译器也不会让你通过)。

然而,int int.Parse(string)bool int.TryParse(string, out int)(以及它们的各种重载)是可行的。

就我个人而言,我主要只在处理反射时使用 Convert,所以对我来说选择是 ParseTryParse。当我期望值是有效的整数并且希望它在无效时抛出异常时,我使用第一个。当我想要检查它是否为有效的整数时,我可以决定在它是/否时该怎么做。


第三段第一句话在第一次阅读时似乎有矛盾之处;它应该是“仅在主要使用Convert时使用”,还是我没有理解? - Dax Fohl
@DaxFohl,他的意思是说如果他在项目中使用了Convert,那么几乎肯定是与反射一起使用的。我理解这意味着,作为更通用的接口,当您不知道是否需要将某个值转换为intdouble、其他某些基本类型或某些用户类型直到运行时时,它非常有用。例如,Convert.ChangeType()对此非常有用。 - binki

5
引用自Eric Lippert文章
转换意味着两个矛盾的事情:“检查此对象是否真的是此类型,如果不是,则抛出异常”和“此对象不属于给定类型;找到一个属于给定类型的等效值”。
因此,在1中尝试做的是断言String是Int。 但是这个断言失败了,因为String不是int。
2之所以成功是因为Convert.ToInt32()解析字符串并返回整数。 它仍然可能失败,例如:
Convert.ToInt32("Hello");

这将导致参数异常。

总之,从字符串转换为整数是一个框架问题,而不是 .Net 类型系统中隐含的内容。


4

一个字符串不能通过显式转换被转换为整数。必须使用 int.Parse 进行转换。

Convert.ToInt32 基本上包装了这个方法:

public static int ToInt32(string value)
{
    if (value == null)
    {
        return 0;
    }
    return int.Parse(value, CultureInfo.CurrentCulture);
}

4

您在谈论C#类型转换与.NET转换工具之间的区别。

  • C#语言级别的类型转换使用括号 - 例如(int) - 它的转换支持有限,依赖于类型之间的隐式兼容性,或者通过转换运算符由开发人员明确定义的指令。
  • .NET Framework中存在许多转换方法,例如System.Convert,用于允许同一或不同数据类型之间的转换

(类型转换)语法适用于数字数据类型,以及“兼容”的数据类型。 兼容意味着通过继承(即基类/派生类)或实现(即接口)建立了关系的数据类型。

类型转换也可以在具有转换运算符定义的不同数据类型之间进行。

另一方面,System.Convert类是许多可用机制中的一种,用于以一般意义上的方式进行转换;它包含了逻辑,可以在逻辑上将可以从一种形式转换为另一种形式的已知不同数据类型之间进行转换。

转换甚至涵盖了与强制转换相同的内容,允许在类似数据类型之间进行转换。


记住,C#语言有自己的做事方式。
而底层的.NET框架也有自己的做事方式,与任何编程语言无关。
(有时它们在意图上重叠。)
将类型转换视为C#语言级别的功能,其性质更为有限,通过System.Convert类进行转换是.NET框架中可用的许多机制之一,用于在不同类型之间转换值。

1

1) C# 是一种类型安全的语言,不允许将字符串赋值给数字。

2) 第二种情况将字符串解析为新变量。如果您的 Session 是 ASP.NET 会话,则无需在其中存储字符串并在检索时将其转换回来。

int iVal = 5;
Session[Name1] = 5;
int iVal1 = (int)Session[Name1];

1

.NET 中没有默认的从字符串到整数的转换。您可以使用 int.Parse() 或 int.TryParse() 来完成此操作。或者,就像您所做的那样,您可以使用 Convert.ToInt32()。

然而,在您的示例中,为什么要先进行 ToString() 然后再将其转换回整数呢?您可以简单地将整数存储在 Session 中,并按如下方式检索它:

int i = Session["name1"];

1
这个问题已经讨论过了,但是我想分享一个dotnetfiddle。
如果你正在处理算术运算并使用float、decimal、double等数据类型,最好使用Convert.ToInt32()。
using System;

public class Program
{
  public static void Main()
  {
    double cost = 49.501;
    Console.WriteLine(Convert.ToInt32(cost));
    Console.WriteLine((int)cost);
  }
}

输出

50
49

https://dotnetfiddle.net/m3ddDQ


1
只是简单的补充一下:在不同的情况下(例如,如果您将double等转换为Int32),在选择这两个之间时,您可能还需要考虑四舍五入的问题。Convert.Int32将使用银行家舍入(MSDN);(int)将仅截断为整数。

0
这可能有点老旧,但另一个区别是,如果你有一个双精度数例如5.7,使用(int)将不会四舍五入,输出结果为5。而如果你使用Convert.ToInt(),数字将会四舍五入到6。

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