字符串、对象和 int 之间的强制转换和分析
本文关键字:转换 之间 对象 int 字符串 | 更新日期: 2023-09-27 18:33:25
ddlSomeDropDownType.SelectedValue
是.aspx
页面的下拉列表。我有以下代码:
int num = int.Parse(((object)this.ddlSomeDropDownType.SelectedValue).ToString());
我是否正确认为会发生以下情况:
- 下拉值(字符串(向下转换为对象
- 对象是一种引用类型,因此
.ToString()
在此实例中不执行任何操作,编译器会省略 - 然后对象被解析为 int:ref type => 值类型
或者 C# 编译器会接受这一点,而不是在不需要的时候强制转换?
下拉值(字符串(向下转换为对象
嗯,是的,但所有的变化都是编译器如何绑定对对象的后续调用。 您告诉编译器"将此值视为object
" 它不会以任何方式更改实际对象。
object 是一种引用类型,因此
.ToString()
在这种情况下不执行任何操作,编译器会省略
否 - 您调用ToString
它是object
上的虚拟方法,因此将调用object.ToString
或后续覆盖(在您的情况下为字符串。ToString(('.
另外,您已经告诉编译器将该值视为object
。 你希望编译器回去说"好吧,我知道你告诉我把它当作一个对象,但我可以从上面的代码中看出它是一个字符串,所以我将忽略它,只把它作为一个字符串"。 编译器不会进行该工作。 JIT 优化器可能会做类似的事情,如果有铁定的保证它会工作;否则它会按照你告诉它做的事情去做。
对象比转换为 int
否 - 它由int
类解析 - 与强制转换非常不同。 它将读取字符串的字符并尝试返回等效的整数值。 原始对象(字符串(保持不变,并创建一个新值(int(。 如果您"更改"原始值(在这种情况下这是不可能的,因为字符串是不可变的,但为了参数起见,让我们假设您可以(,那么解析后的整数将不会更改。 如果将对象强制转换为 int,然后更改字符串,则它们都引用相同的值,因此更改将反映在两者中。
由于SelectedValue
是一个字符串,因此无需强制转换为对象然后调用ToString()
,因此您的代码可以简化为
int num = int.Parse(this.ddlDiscountType.SelectedValue);
不,不是真的。
首先,您需要了解运行时类型信息和编译时类型信息之间的区别。
ddlDiscountType.SelectedValue
的编译时类型为 string
。当您将其转换为 object
时,它不会更改运行时类型,只会更改编译时类型 - 实际上,您减少了引用的公共接口。
ToString
是一个虚拟方法,所以只要你不使用 new
,发生的情况取决于运行时类型,并且与编译时类型无关,只要该方法是在编译时类型中定义的。由于ToString
是在Object
上定义的,因此没有问题。
编译器无法删除对ToString
的调用,因为您已经明确表示"不,此引用不是真正的字符串。它只是一个对象",因此您必须进行虚拟方法调用。调用将使用引用的运行时类型,因此您正在执行 String.ToString()
,它只返回 this
。但是你尽了最大的努力来干扰编译器,编译器不会事后猜测你。
最后,int.Parse
将解析字符串并输出一个整数。当然,这涉及通过字符串逐个字符地进行。引用和值类型在这里并不重要 - 它不是强制转换,而是与其他任何方法调用一样的方法调用。该方法将字符串转换为数字,仅此而已。强制转换只会抛出一个InvalidCastException
,因为字符串不是整数(尽管如果你创建自己的类型,你可以提供自己的强制转换方法,它可以做任何你想让他们做的事情(。编译器无法告诉您不能将字符串转换为整数,因为您刚刚说引用实际上不是字符串,而是object
- 并且object
可以转换为int
,如果它引用的运行时类型是盒装int
。
没有理由以如此复杂的方式做事。只需做:
var number = int.Parse(ddlDiscountType.SelectedValue);
花精力添加适当的错误处理,而不是做愚蠢的仪式:)
1:这是不正确的。"下拉值(字符串(被向上转换为对象"。.NET Framework 中的所有类都派生自 object。(向基类投射是向上投射。
2: a(是,对象是引用类型。
b(.ToString是对象类方法(可以被派生类覆盖(。实际上这里发生的事情是那个int。解析采用字符串参数。为此,您首先将其隐藏到对象中,然后.ToString 方法调用。
3:是的 第三点是正确的