在int和string中装箱和拆箱

我在拳击和拆箱方面有点困惑。 根据其定义

Boxing是ValueTypes到引用类型(Object)的隐式转换。
UnBoxing是将引用类型(Object)显式转换为其等效的ValueTypes。

描述这个的最好例子是

int i = 123; object o = i; // boxing 

 o = 123; i = (int)o; // unboxing 

但我的问题是int是否是值类型而字符串是引用类型

 int i = 123; string s = i.ToString(); 

 s = "123"; i = (int)s; 

这是拳击和拆箱的例子吗?

调用ToString不是装箱。 它创建了一个恰好包含int的文本表示的新字符串。

调用(object)1会在堆上创建一个包含int的新实例。 但它仍然是一个int 。 (您可以使用o.GetType()validation)

无法使用强制转换将字符串转换为int 。 所以你的代码不会编译。

如果你首先将你的字符串转换为object你的代码将被编译但在运行时失败,因为你的对象没有盒装int。 您只能将值类型拆分为完全正确的类型(或关联的可为空)。

两个例子:

破碎:

 object o=i.ToString();// o is a string int i2=(int)o;//Exception, since o is no int 

工作:

 object o=i;// o is a boxed int int i2=(int)o;//works 
  int i = 2; string s = i.ToString(); 

不是拳击。 这只是对Int32.ToString()的方法调用,它返回一个表示int值的格式化字符串。

  i = (int)s; 

此代码将无法编译,因为System.StringSystem.Int32之间没有定义显式转换。

可以通过以下方式来理解它是什么以及什么不是装箱拆箱

  1. 拳击:当你采用值类型并将其“粘贴”在引用变量中时。 此操作无需任何特定类型的转换逻辑。 如果使用GetType() ,变量类型仍将是相同的。

  2. 拆箱:它只是相反的操作。 获取卡在引用对象中的值类型,并将其分配给值类型变量。 同样,不需要任何特定类型的转换逻辑来使该操作起作用。

    因此,如果(int)s有效,它只是一个显式转换,而不是一个拆箱操作,因为s.GetType()将返回System.String ,而不是System.Int32

Boxing / Unboxing:将值类型转换为其对象表示,反之亦然(例如int和object)。

相比之下,ToString()方法是一个生成新字符串的操作,与装箱/演员/类型会话无关。

迟到了,但是……我不喜欢简单地阅读答案而没有背后的证据。 我喜欢理解这个问题并分析可能的解决方案,看看它是否与我的理解相关。 来自神杰夫里希特的正确广受欢迎的’CLR via C#’的复制和粘贴文字解释了这一点:

即使未装箱的值类型没有类型对象指针,您仍然可以调用由类型inheritance或覆盖的虚方法(如Equals,GetHashCode或ToString)。 如果您的值类型覆盖其中一个虚方法,那么CLR可以非虚拟地调用该方法,因为值类型是隐式密封的,并且不能具有从它们派生的任何类型。 此外,用于调用虚方法的值类型实例不会加框。 但是,如果重写虚方法会调用基类型的方法实现,那么在调用基类型的实现时,值类型实例会被装箱,以便对堆对象的引用传递给this指针到基类方法。 但是,调用非虚拟inheritance方法(例如GetType或MemberwiseClone)总是需要将值类型装箱,因为这些方法是由System.Object定义的,因此方法期望this参数是一个引用该对象的指针。堆。

里希特先生应该获得这本书的奖章。 如果你还没有,那就去吧! 然后你会得到它:)