开发者

Boxing, a thing of the past?

Is there any point in doing this?

public static void Write<T>(T value)
{
    textWriter.Write(value.ToString());
}

...as supposed to this:

public static void Write(object value)
{
    textWriter.Write(value.ToString());
}

Setting aside the obvious null dereference possibility, If I where to write a lot of value types using this method wouldn't the former be much better because it will have it's own version of the write method to call, or is it just gonna bloat the binary in terms of a lot of additional code being generated?

The performance implication of such a thing mi开发者_如何学JAVAght be negligible, but I'm curious, it's a lot more compact than providing an overload for each and every value type in the BCL, like most writers in the BCL already do.


From what I understand, in both cases boxing occurs.

The latter is obvious as the value is already boxed.

The former is less obvious, but as a virtual method is called on a valuetype, it will need to be boxed to perform the callvirt.

Edit: I just checked the emitted IL, and there is no explicit boxing occuring in the generic case. Something rings a bell though.

Edit 2: I might have been confusing myself with the case using interfaces. There clearly boxing occurs.

Edit 3: Boxing does occur, if ToString() is not overriden in the value type.

I get this from ECMA-335 part 3 pg 25 (only noting the last case):

If thisType is a value type and thisType does not implement method then ptr is dereferenced, boxed, and passed as the ‘this’ pointer to the callvirt of method

This last case can only occur when method was defined on System.Object, System.ValueType, or System.Enum and not overridden by thisType. In this last case, the boxing causes a copy of the original object to be made, however since all methods on System.Object, System.ValueType, and System.Enum do not modify the state of the object, this fact can not be detected.

Edit 4: Here is a similar question on SO.


Yes, it will avoid boxing in most cases. I wouldn't expect that to make any significant performance difference in most cases though. As you say yourself, it's likely to be negligible.

I'd argue that it does add a bit of a burden in terms of readability though. I suspect that most people have a bit more cognitive load when trying to understand a generic method than they do a simple method taking object. Who's going to be using this method, and are they sufficiently happy with generics that it won't bother them?


  • virtual calls can require boxing (as leppie already said)
  • the generic is more compact in source, but not in JIT'ed code

Considering performance:

  • the generic reduces binary size somewhat. JIT time and code locality remain the same, since only required overloads are jitted anyway
  • if the method is not a simplistic as in the example, the boxing solution will involve less JIT calls and decrease code size (thus improving locality as well). This is an accumulative effect hard-to-measure except in extreme cases.

The gist is: there's no one perfect method for all circumstances.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜