在为整数类型调用ToString时是否涉及到装箱?

时间:2014-11-25 16:37:00

标签: c# .net boxing

非常简单的问题:

int a = 5;
string str = a.ToString();

由于ToString是System.Object的虚方法,这是否意味着每当我为整数类型调用此方法时,都会发生装箱?

6 个答案:

答案 0 :(得分:12)

你已经得到了答案,告诉你当ToString()覆盖一个值类型时,你调用它时就没有拳击,但是有一些方法可以实际看到它。

采用int?Nullable<int>)类型。这是一个有用的类型,因为它是一个值类型,但装箱可能会产生一个空引用,并且无法通过空引用调用实例方法。它确实有一个重写的ToString()方法。它没有(也没有)被覆盖的GetType()方法。

int? i = null;
var s = i.ToString(); // okay: initialises s to ""
var t = i.GetType(); // not okay: throws NullReferenceException

这表明在电话i.ToString()中没有拳击,但在电话i.GetType()中有拳击。

答案 1 :(得分:3)

不,拳击不会发生。调用虚方法时,CLR查找类型对象指针以从方法表中获取实际的重写方法。对于值类型,没有对象指针,因此直接进行非虚拟调用,JIT知道没有polimorphic副作用,因为值类型是密封的。但是,如果ToString()值类型调用base.ToString(),则可能会发生装箱:然后将实际实例装箱并传递给System.ValueType.ToString()
Int32.ToString()不会调用base.ToString()并使用本机实现,因此不会发生装箱。

答案 2 :(得分:3)

其他答案提到ToString调用不会导致拳击。它无关紧要:

int i = 42;
String.Format("number: {0}", i.ToString());

不会导致拳击,而:

int i = 42;
String.Format("number: {0}", i);

意愿。

(你听说过,Resharper?)

(但请注意,如果您将格式化程序应用于String.Format(例如CultureInfo,则需要使用第二个版本)

答案 3 :(得分:2)

当您对Int32.ToString()调用进行反编译时,您可以看到它实现了FormatInt32这是本机C ++方法。该方法实现如下:

public override string ToString()
{
    return Number.FormatInt32(
    this,
    null,
    NumberFormatInfo.CurrentInfo);
}

[MethodImpl(MethodImplOptions.InternalCall)]
public static extern string FormatInt32(
    int value,
    string format,
    NumberFormatInfo info);

调用Int32ToDecChars

wchar_t* COMNumber::Int32ToDecChars(
wchar_t* p,
unsigned int value,
int digits)
{
    LEAF_CONTRACT
    _ASSERTE(p != NULL);

    while (--digits >= 0 || value != 0) {
        *--p = value % 10 + '0';
        value /= 10;
    }
    return p;
}

它需要每个数字,转换为单独的char并存储在字符串中。然后返回该字符串。所以没有涉及int拳击。

在此链接下,您可以找到在ToString()上调用int时实际发生的事情的相当详尽的说明。作为奖励,本文还解释了Int32.Parse()背后的所有机制:

https://selvasamuel.wordpress.com/2008/03/14/boxingunboxing-in-net/

答案 4 :(得分:1)

由于在ToString类中覆盖Int32 - 否,在这种情况下不会有装箱,因为object上不会创建任何实例。

由于动态调度,调用Int32的简单方法。

答案 5 :(得分:-5)

这取决于在Int32类中如何实现ToString()函数。自.net框架实现以来,我们无法确认拳击是否发生。