[英]C# object looks like dynamic type
一直在使用4.0 DLR,并将动态与对象进行比较并遇到了这样的情况:
码:
object x = 10;
Console.WriteLine("x = {0} and is a {1}.\n", x, x.GetType());
x = (int)x + 3;
Console.WriteLine("x = {0} and is a {1}.\n", x, x.GetType());
x = x + "a";
Console.WriteLine("x = {0} and is a {1}.\n", x, x.GetType());
结果:
x = 10并且是System.Int32。
x = 13并且是System.Int32。
x = 13a并且是System.String。
对我来说,看起来对象试图在运行时(动态)使对象适合类型。 但是,如果我没有将x转换为第3行的int,它会给我一个编译器区域,这对于静态类型来说似乎是正确的。 但是它允许我向x添加“a”,现在它将其识别为字符串。
我错过了什么?
您错过了+
运算符在应用于字符串时执行自动转换(通过在不是String
类型的实例的操作数上调用.ToString()
方法.ToString()
这一事实。
来自C#语言规范 :
7.8.4加法运算符
当一个或两个操作数是字符串类型时,预定义的加法运算符会连接操作数的字符串表示形式。
字符串连接:
string operator +(string x, string y); string operator +(string x, object y); string operator +(object x, string y);
二进制+运算符的这些重载执行字符串连接。 如果字符串连接的操作数为
null
,则替换空字符串。 否则,通过调用从类型对象继承的虚拟ToString
方法,将任何非字符串参数转换为其字符串表示形式。 如果ToString
返回null
,则替换空字符串。
请记住, 变量的类型( object
)与它引用的对象的类型之间存在区别。
允许最后一次转换,因为System.String
类型定义了一个操作符,该操作符接受一个object
作为其中一个值并对其执行自动ToString()
。
运行时或动态操作没有任何有趣的业务。
对我来说,看起来对象试图在运行时(动态)使对象适合类型。
不是真的:它只是简单地运用.NET object
存储任何类型object
的能力。
例如,为了变得dynamic
,变量应该允许你在没有强制转换的情况下调用任何东西
dynamic x = "hello";
dynamic y = x.Substring(0, 2); // The compiler does not complain
如果你尝试使用“普通” object
来完成上述技巧,你会得到编译器的愤怒信息。 然而, dynamic
的使用推迟到运行时间,此时它可能发生,或者根本不会发生。
但是它允许我向x添加“a”,现在它将其识别为字符串。
这是编译器的“魔力”:它知道object
有一个ToString
,并自动为你插入调用。
由于C#中的所有类型都是从对象类型派生的,因此它可以存储任何类型 。
object x = 10;
x = x + "a";
这就是编译器实际做的事情。 由于object
有.ToString()
,当你使用+
,编译器会自动调用它。
即使我们看到这个的IL代码;
.locals init ([0] object x)
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: box [mscorlib]System.Int32
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: ldstr "a"
IL_000f: call string [mscorlib]System.String::Concat(object,
object)
此String.Concat
方法的返回值是值的string
表示形式。
来自C#5.0规范 :
字符串连接:
string operator +(string x, string y); string operator +(string x, object y); string operator +(object x, string y);
二进制+运算符的这些重载执行字符串连接。 如果字符串连接的操作数为
null
,则替换空字符串。 否则,通过调用从类型对象继承的虚拟ToString
方法,将任何非字符串参数转换为其字符串表示形式。 如果ToString
返回null
,则替换空字符串。
C#中的所有内容都继承自object
。 int
, string
, char
等都可以。
当你这样做:
object x = 10;
你要创建一个变量x
,然后将其初始化为整数值10的值是一个int
,它只是被boxed
到对象。
当你将x
为int
你将它unboxing
到它的实际类型。
查看本指南的拳击和拆箱
c#上的所有数据类型都继承自“object”,因此任何操作的基本行为都取决于运算符和其他对象
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.