在C#中,何时使用cast和convert是合适的?

10

我一直认为在C#中转换和转化基本上是相同的:从一个数据类型到另一个数据类型的两种不同方式。然而,显然这是不正确的,因为它们经常会输出不同的结果。

Convert.ToInt32(1.6)     //outputs 2
(Int32)1.6               //outputs 1


(DateTime)("10/29/2013")          //won't compile - cannot convert type 'string' to type 'system.date.time'
Convert.ToDateTime("10/29/2013")  //outputs 10/29/2013 12:00:00 AM
  • 我的问题是这两个方法的主要区别是什么,为什么它们返回不同的结果?
  • 在什么情况下使用其中一个方法比另一个更加合适?

个人认为使用Convert.To方法更加简洁明了。我知道它还会抛出System.InvalidCastException异常。有没有人能够提供一个简单明了的解释呢?


1
Convert 在转换时会进行一些“魔法”操作。它会分析源类型的值并应用转换来创建目标类型的新实例。强制转换发生在较低级别,您只能将相关类型进行强制转换(例如将浮点数转换为整数)。 - knittl
@Kelix,你的示例回答了你自己的问题。通常情况下,当你有继承关系时应该使用强制类型转换。当你无法进行强制类型转换时,使用Convert将一种东西转换为另一种东西。 - Candide
3个回答

5

您可以在两种情况下使用转换(cast):

在所有其他情况下,您应该使用Convert或其他自定义转换方法(例如DateTime.Parse)。

为什么它们返回不同的结果?

因为执行不同的代码。Convert.ToInt32(double value)会对转换的结果进行四舍五入:

int num = (int) value;
double num2 = value - num;
if ((num2 > 0.5) || ((num2 == 0.5) && ((num & 1) != 0)))    
    num++;

return num;

1
在转换中,Convert.ToInt32 方法使用以下规则来返回其值:

将值四舍五入为最接近的 32 位有符号整数。如果值恰好处于两个整数之间,则返回偶数;即 4.5 转换为 4,5.5 转换为 6。

然而,显式转换 的规则是不同的:

当您将十进制值转换为整数类型时,该值会向零舍入到最接近的整数值。如果结果整数值超出了目标类型的范围,则会引发 OverflowException 异常。

如果您希望转换的方式与Convert.ToInt32相同[或者想要指定舍入方式],则应使用以下强制转换的Math.Round方法。
(int)Math.Round(1.6) //outputs 2

还有其他的方法签名可以让您指定如何进行舍入。

至于何时应该使用 cast 和 convert,当可能使用 显式转换 时应该使用 cast (意识到从更精确的类型到 less 精确的类型会丢失精度并适当处理),而在数据不被预期为可以转换的格式时使用 convert。 可能时 意味着存在显式转换(包括隐式转换)。预定义的转换可以在规范的第6节中找到。

形式为 (T)E 的 cast-expression,其中 T 是一种类型,E 是一个 unary-expression, 执行 E 的值到类型 T 的显式转换(第6.2节)。如果从 E 的类型到 T 不存在显式转换,则会在编译时出错。 否则,结果是显式转换产生的值。


0

在所有情况下都没有快速规则可供使用。您只需要知道每个操作的作用,并选择最适合您场景的操作。就像您所指出的那样,转换和强制转换可能会产生不同的结果。原因是转换和强制转换可以具有完全不同的实现方式。

public static explicit operator MyStructA(MyStructB b)  
{
    MyStructA a = convert.ToMyStructA(b); 
    //I could do this so that convert and cast return the same but I don't have to.

    return a;
}

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