[Mono-devel-list] Performance w/ boxing

Jonathan Gilbert 2a5gjx302 at sneakemail.com
Fri Feb 20 22:33:52 EST 2004


At 07:36 AM 20/02/2004 -0500, Jonathan Pryor jonpryor-at-vt.edu |mono-list
subscription| wrote:
>Below...
>
>On Fri, 2004-02-20 at 02:51, Piers Haken wrote:
>> Yeah, just use  
>> 
>> 	void function (ref int a) {}
>> 
>> You can pass references to unboxed ints, boxed ints, or fields, however you
>> can't pass indexers or properties.
>
>That's not quite what the original poster (Jaroslaw Kowalski) wanted. 
>He wanted a way to check for either (a) null, or (b) a boxed integer.  A
>"ref" or "out" integer can never be null.

This isn't quite right. An 'out' parameter is in fact uninitialized and
does not carry any value at all. A 'ref' parameter must not be
uninitialized in the calling context when it is passed to the function, but
it may be initialized to 'null'. 'null' is not an uninitialized value, it
is explicit initialization to a null reference. If 'null' cannot be passed
for a 'ref object' parameter, then '0' cannot be passed for a 'ref int'
parameter :-) Remember that the reference that 'ref' refers to is a
reference to the variable in the calling context, and not to the object to
which that variable refers. Whew, too many 'ref's in that sentence :-)

An 'object' can be checked for a boxed value type with the 'is' operator.
However, it isn't possible to restrict the type of the object that may be
boxed for a given call, not in C# or CIL, because it's impossible to tell
what an 'object' reference variable will refer to at compile time. That
said, the function can always complain at runtime, which is about as good
as it gets.

void function(ref object boxed)
{
  if (boxed == null) { do something }
  else if (boxed is int) { do something else using (int)boxed }
  else throw new InvalidArgumentException("boxed", "Parameter should be
'null' or a boxed int");
}

void caller(bool pass_null)
{
  object meaning_of_life = pass_null ? null : 42;

  function(ref meaning_of_life);
}

Of course, you can always do it Java-style and create a class to wrap an
integer. You can use operator overloading to make it transparent, too.

public class Integer
{
  public readonly int Value;
  public Integer(int value) { Value = value; }
  public static implicit operator int(Integer obj) { return obj.Value; }
  public static implicit operator Integer(int val) { return new
Integer(val); }
}

void function(Integer manually_boxed)
{
  if (manually_boxed == null) { do something }
  else { do stuff using manually_boxed; it can be placed directly into an
expression, as it will implicitly convert to an 'int' }
  // no exception throwing needed, since 'Integer' can only box ints
}

The performance of this would likely be somewhat lower than that of actual
boxing, since the 'Integer' class is not special-cased by the runtime as a
box, but the semantics in the source code are much nicer in my opinion. :-)

Jonathan Gilbert




More information about the Mono-devel-list mailing list