38

我今天刚遇到这个,如果你将 null 转换为 int32

Convert.ToInt32(null)

它返回 0

我期待一个 InvalidCastException ......

知道为什么会这样吗?

4

6 回答 6

47

知道为什么会这样吗?

因为那是记录在案的行为?无论是Convert.ToInt32(object)还是Convert.ToInt32(string),文档都非常清楚地说明:

(在返回值下)

一个 32 位有符号整数,等于 value 中的数字,如果 value 为 null,则为 0(零)。

或者

等效于 value 的 32 位有符号整数,如果 value 为空,则为零。

与往常一样,如果现实与期望不符,您应该做的第一件事是检查您的期望是否与记录的行为相符。

就我个人而言,我并不完全认同 Gavin 所展示的“与 VB6 的兼容性”论点。我意识到它来自微软,这很可能是它表现得那样的真正原因——但我认为这不是表现得那样的理由。有很多 VB 特定的转换方法——所以如果框架设计者真的认为返回零是一个不理想的结果,他们应该做他们认为最好的任何事情,并提供一个 VB6 兼容的转换供 VB6 程序员使用。

显然,一旦在 .NET 1.0 中定义了该行为,就不能为以后的版本更改它——但这与说它必须以与 VB6 相同的方式运行是不同的。

于 2012-07-20T13:22:42.333 回答
13

请参阅http://msdn.microsoft.com/en-us/library/sf1aw27b.aspx

编辑

上面的 URL 会自动恢复到最新的 Framework 版本,因为下面的文本是专门在版本 4 上发布的。请参阅下面显示文本的修改后的 URL。

http://msdn.microsoft.com/en-us/library/sf1aw27b(v=vs.100).aspx

它解释说:

如果字符串为空,则 Convert 类中的所有字符串到数字的转换方法都返回零。这种行为的最初动机是他们将为从 Visual Basic 6 迁移到 Visual Basic .NET 的程序员提供一组转换方法,以反映现有 Visual Basic 6 转换方法的行为。假设是 C# 程序员更愿意使用转换运算符,而 Visual Basic 传统上使用转换方法进行类型转换。

传统上,.NET Framework 试图保持版本之间的高度兼容性。实际上,这意味着,在没有非常令人信服的理由的情况下,一旦以特定方式实现了方法并且该实现公开(如在字符串参数为 null 时返回 0 的方法中),它就无法更改,因为会破坏依赖于既定行为的代码。这使您提出的两个解决方案都非常成问题。在第一种情况下,对于可能依赖为空字符串返回零的方法的客户,抛出异常会更改方法的实现。在第二种情况下,重要的是要记住 .NET Framework 在重载决议中不考虑返回类型。这意味着您的方法必须替换现有的 Convert。

在 Convert 类中的字符串到数字的转换方法的情况下,这种对兼容性的关注更加强烈,因为 Parse 是为 .NET 支持的每种基本数字类型执行字符串到数字的转换的推荐方法框架,并且每个 Parse 方法的行为与其对应的 Convert 方法不同。与 Convert 类中的字符串到数字的转换方法(如果要转换的字符串为 null 时返回零)不同,每个 Parse 方法都会引发 ArgumentNullException,这是您争论的行为。数字 Parse 方法的重载,例如 Int32.Parse 和 Double.Parse,还具有允许对解析操作进行更细粒度控制的优点。

于 2012-07-20T13:22:48.743 回答
5

因为 Int32 的默认值为零。Int32 不能为 null,因为它们是值类型,而不是引用类型,因此您将获得默认值。

于 2012-07-20T13:21:26.187 回答
5

因为这就是记录它将返回的内容。也许你在想(int)null,这将是一个NullReferenceException(不是InvalidCastException;我不知道为什么)。

于 2012-07-20T13:21:55.383 回答
3

因为这是在 Convert 类中编写方法的方式。如果参数值是null它只是返回 0。

public static int ToInt32(object value)
{
    if (value == null)
    {
        return 0;
    }
    else
    {
        return ((IConvertible)value).ToInt32(null);
    }
}
于 2012-07-20T13:24:24.260 回答
2

为了让您拥有 InvalidCastException,您必须进行非受控演员表。

例如:

int i = (int)null;

如果你执行它,应该引发异常。

指某东西的用途

Convert.ToInt32(var)

当您不信任var中的值时很有用,例如从数据库中读取。

于 2014-08-25T11:15:57.657 回答