5

一直在玩 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。

对我来说,看起来对象试图在运行时(动态)使对象适应类型。但是,如果我不在第 3 行将 x 转换为 int,它会给我一个编译器区域,这对于静态类型来说似乎是正确的。但随后它允许我向 x 添加一个“a”,现在它将它识别为一个字符串。

我错过了什么?

4

7 回答 7

6

您错过了这样一个事实,即+运算符在应用于字符串时会进行自动转换(通过调用.ToString()不是该String类型实例的操作数上的方法)。

于 2013-02-19T20:45:38.720 回答
4

From the C# Language Specification:

7.8.4 Addition operator

When one or both operands are of type string, the predefined addition operators concatenate the string representation of the operands.

  • String concatenation:

    string operator +(string x, string y);
    string operator +(string x, object y);
    string operator +(object x, string y);
    

    These overloads of the binary + operator perform string concatenation. If an operand of string concatenation is null, an empty string is substituted. Otherwise, any non-string argument is converted to its string representation by invoking the virtual ToString method inherited from type object. If ToString returns null, an empty string is substituted.

于 2013-02-19T20:50:30.517 回答
2

请记住,变量的类型(即object)和它引用的对象的类型是有区别的。

允许最后一次转换,因为该System.String类型定义了一个运算符,该运算符接受 anobject作为值之一并对其执行自动ToString()操作。

运行时或动态操作没有什么好玩的。

于 2013-02-19T20:48:15.337 回答
1

对我来说,看起来对象试图在运行时(动态)使对象适应类型。

并非如此:它只是锻炼了 .NETobject存储任何类型对象的能力。

为了成为dynamic,一个变量应该允许你在没有强制转换的情况下调用任何东西,例如

dynamic x = "hello";
dynamic y = x.Substring(0, 2); // The compiler does not complain

如果您尝试使用 "plain" 来完成上述技巧object,您会收到来自编译器的愤怒消息。但是,使用dynamic将抱怨推迟到运行时,此时它可能会发生,也可能根本不会发生。

但随后它允许我向 x 添加一个“a”,现在它将它识别为一个字符串。

那是编译器所做的“一件魔术”:它知道object有 a ToString,并自动为您插入调用。

于 2013-02-19T20:46:51.340 回答
1

由于 C# 中的所有类型都派生自对象类型,因此它可以存储任何类型

object x = 10;
x = x + "a";

那就是编译器实际上所做的。由于objecthas .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否则,通过调用从类型 object 继承的虚拟方法,将任何非字符串参数转换为其字符串表示形式。如果ToString返回null,则替换为空字符串。

于 2013-02-19T20:52:40.243 回答
0

all data types on c# inherited from "object" so the basic behaviour on any operation depends on the operator & the other object

于 2013-02-19T20:50:03.723 回答
0

C# 中的所有内容都继承自object. int, string, char, 等等都可以。

当你这样做时:

object x = 10;

您正在创建一个变量 ,x然后将其初始化为整数值 10。该值是int,它只是boxed放入一个对象中。

当您转换为时xint您就是unboxing它的实际类型。

查看本指南以了解装箱和拆箱

于 2013-02-19T20:46:21.913 回答