code more efficient for generic containers when they contain valuestype

P

puzzlecracker

Allegedly, they are more efficient than their non-generic counterparts
because they avoid boxing.

How is it possible to avoid boxing whenever generic code is used?
Wouldn't autoboxing still require whenever open type is expended and
used for value types as in the example below:

List<int> list=new List<int>();

list.Add(5); //Wouldn't this auto-box into Integer?

Thanks
 
P

puzzlecracker

Allegedly, they are more efficient than their non-generic counterparts
because they avoid boxing.

Not allegedly. They are.
How is it possible to avoid boxing whenever generic code is used?
Wouldn't autoboxing still require whenever open type is expended and
used for value types as in the example below:
List<int> list=new List<int>();
list.Add(5); //Wouldn't this auto-box into Integer?

No. For value types, a whole new instance of the type is created for each
different type used as a type parameter for the class. So, when you use
List<int>, you get a version of List<T> that uses unboxed ints inside.

Using the Add() method as an example, here's a simplified version of
what's going on. The class might look something like this:

class List<T>
{
// Default storage length is 4 elements
private T[] _rgt = new T[4];
private _ctCur;
private _ctMax = 4;

public void Add(T t)
{
if (_ctCur == _ctMax)
{
// reallocate and copy to make room (code not shown here)
}

_rgt[_ctCur++] = t;
}
}

When you use the class as List<int>, a new type is created where "T" is
replaced by "int" everywhere. So the class winds up being like this:

class List<int>
{
// Default storage length is 4 elements
private int[] _rgt = new int[4];
private _ctCur;
private _ctMax = 4;

public void Add(int t)
{
if (_ctCur == _ctMax)
{
// reallocate and copy to make room (code not shown here)
}

_rgt[_ctCur++] = t;
}
}

And you'll note that in the above, there's no need to box the parameter to
the Add() method when it's called. It simply is passed and used as any
other value type might be.

Note that the reified generic type is handled different for value types
and reference types. For a reference type, there's no need to create a
whole new reified version of the generic type for each different reference
type used; the same code can be reused, and internally it just deals with
the references. But in order to avoid boxing of value types, a new type
has to be built for each different value type that is used as a type
parameter for the generic type. If you had a List<int> and a List<double>
in your program, that would result in two completely different reified
types being created from the generic type.

Pete

Good explanation...
 
B

Ben Voigt [C++ MVP]

Peter said:
How is it possible to avoid boxing whenever generic code is used?
Wouldn't autoboxing still require whenever open type is expended and
used for value types as in the example below:

List<int> list=new List<int>();

list.Add(5); //Wouldn't this auto-box into Integer?

No. For value types, a whole new instance of the type is created for
each different type used as a type parameter for the class. So, when
you use List<int>, you get a version of List<T> that uses unboxed
ints inside. [snip]

Note that the reified generic type is handled different for value
types and reference types. For a reference type, there's no need to
create a whole new reified version of the generic type for each
different reference type used; the same code can be reused, and
internally it just deals with the references. But in order to avoid
boxing of value types, a new type has to be built for each different
value type that is used as a type parameter for the generic type. If
you had a List<int> and a List<double> in your program, that would
result in two completely different reified types being created from
the generic type.

IOW, .NET generics with value type parameters don't use erasure. Since Java
does use erasure for all generics, .NET performance is considerably better
in this area.

I'm comparing with Java because of the words "open type" and "Integer" (with
a capital I). .NET doesn't have a type called Integer, it's System.Int32.
OTOH in Java it would be java.lang.Integer
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top