Boxing and Unboxing ??

  • Thread starter Thread starter Peter Olcott
  • Start date Start date
Peter Olcott said:
I can only put in a little time to learn the language now. I am focusing this
time on assessing the feasibility of using C# and .NET for my future needs. It
looks like C# does have the performance that I need. In order to get this
performance, I must use relatively obscure nuances of C# that are barely
mentioned in even the most comprehensive textbooks. Specifically because of this
newsgroup thread, I was able to learn these relatively obscure nuances. It
definitely looks like C# and .NET will be the future of essentially ALL MS
Windows development.

No, in order to get good performance you need to accept things like
"don't make huge value types". That's a much better solution than
creating a large value type and passing it by reference.

Please, just try to work *with* the platform instead of fighting
against it.
 
Hi,

|
| I still don't see any reason why a completely type safe language can not
be
| constructed without the need for any runtime overhead. You could even
allow
| construct such as the above, and still be completely type safe, merely
disallow
| type casting.

You cannot, Type casting is in the core of OOP , IIRC all the languages
support it in some form.


| Global data is disallowed?

Depend of what you understand for that? You can have a data that is
accesible from anywhere in your program. Does this satisfy your globallity?
 
Hi,

| So with Generics Boxing and UnBoxing beomes obsolete?

Not at all.

Generics simply offer the mechanisn for you not to be forced to use a
"cover all instances type" type when you declare a class. Before generics
you used to declare collections as storing objects. as you knew for sure
that EVERYTHING could be converted to an object reference (this imply boxing
with value types). This allowed you to write ONE ArrayList class and use it
with any kind of types.
Of course you could always write one for each value type plus one for
references type this would prevent boxing/unboxing

Now with generic you are taking the second approach one level further. It's
the compiler now who create that class for you at compile time.


But boxing/unboxing will still be there, forever and ever :)
 
Jon Skeet said:
No, in order to get good performance you need to accept things like
"don't make huge value types". That's a much better solution than
creating a large value type and passing it by reference.
There are some cases where this suggestion would be bad design. The case in mind
is similar to the cases where a "friend" function is used in C++.
 
Ignacio Machin ( .NET/ C# MVP ) said:
Hi,

|
| I still don't see any reason why a completely type safe language can not
be
| constructed without the need for any runtime overhead. You could even
allow
| construct such as the above, and still be completely type safe, merely
disallow
| type casting.
I was not referring to polymorphic type casting. I was referring to such things
such as casting an integer to a function pointer.
You cannot, Type casting is in the core of OOP , IIRC all the languages
support it in some form.

Does polymorphic type casting require an explicitly specified cast, or could
this possibly be implicitly performed behind the scenes?
 
Ignacio Machin ( .NET/ C# MVP ) said:
Hi,

| So with Generics Boxing and UnBoxing beomes obsolete?

Not at all.

Generics simply offer the mechanisn for you not to be forced to use a
"cover all instances type" type when you declare a class. Before generics
you used to declare collections as storing objects. as you knew for sure
that EVERYTHING could be converted to an object reference (this imply boxing
with value types). This allowed you to write ONE ArrayList class and use it
with any kind of types.
Of course you could always write one for each value type plus one for
references type this would prevent boxing/unboxing

Now with generic you are taking the second approach one level further. It's
the compiler now who create that class for you at compile time.


But boxing/unboxing will still be there, forever and ever :)
I don't think so.
 
Peter said:
It means that I can't afford to waste any time, and must find shortcuts to
achieve the required end-results.

If you can not afford to waste time, then shortcuts are too risky.

Arne
 
Peter said:
It
definitely looks like C# and .NET will be the future of essentially ALL MS
Windows development.

C# and to some extent VB.NET will take over most of Windows
development that are not required to be highly portable to
other OS's or required to access hardware very directly.

But hopefully the people writing the code will have
time to read about and understand C# and .NET.

Arne
 
Peter said:
Add [in] remove [ref] the net difference is no more elements. However we are
adding one simple parameter qualifier and removing a complex qualifier.

You *never* remove features from a language.
There is no useful distinction between [ref] and [out].

There is a semantic difference in that code exist where one
of them will give a compiler error and the other will not.

There is a clear indication of different intentions by
using the two different keywords.

You may not find the distinction useful, but that does
not preclude that other people do.

Arne
 
Arne Vajhøj said:
If you can not afford to waste time, then shortcuts are too risky.

Arne

That depends on what the short cuts are. One of my shortcuts was to embed a
third party computer language in my product rather than write my own computer
language from scratch. Another short-cut is forming a partnership with an
existing marketing company, rather than handling the direct sales myself.
 
Peter said:
If a C# programmer lacks the ability to see inside his head the underlying
machine code corresponding to the specified C# code, then this programmer lacks
a sufficient understanding of C# and .NET.

This is not the 1980's.

Leave that stuff to the compiler and runtime library writers.
For business apps that read and write text to databases, this won't make much of
a difference. To the author of the database management system itself, this makes
a significant difference. The difference is between excellent quality and
mediocrity.

No. The performance of a database is not determined by optimizing
code based on micro benchmarking. It is determined by high level
design of locking, caching, query plan etc..

Arne
 
Arne Vajhøj said:
Peter said:
Add [in] remove [ref] the net difference is no more elements. However we are
adding one simple parameter qualifier and removing a complex qualifier.

You *never* remove features from a language.

Ever hear of deprecation?
There is no useful distinction between [ref] and [out].

There is a semantic difference in that code exist where one
of them will give a compiler error and the other will not.

There is a clear indication of different intentions by
using the two different keywords.

I think that it is possible to take the .NET platform one large step further in
its abstraction of the underlying details. This large step would be to make the
issue of reference type and value type so transparent to the end user of the
respective languages that no one except .NET compiler writers even need bother
to learn the difference between them.
 
Barry said:
I think doing a lot of interop effectively requires a fair amount of
knowledge of what the CLR is doing. In particular, there are some almost
sneaky things the CLR can do, such as the GC collecting your class
before its methods finished executing, that can cause insidious bugs.

True.

But that is still interface/functional not really
"under the hood".
Perhaps, but I doubt things like Windows, CPUs and caches / memory
hierarchies are going away anytime soon, and you need to have an idea of
the behaviour of those guys, even if it's simple rules of thumb, like
"row-then-column" rather than "column-then-row" when iterating through
large 2D arrays, or writing asynchronous code to avoid thread-switching
overhead, etc.

I can agree on that.

There are something that are good to do on almost any current
or future within a reasonable time horizon.

I say stop when we come to optimizing stuff for x86, x86-64, IA-64 etc..
Sure, if one is tweaking one's code so it inlines "just so", or adds
comments like:

// not creating variable for this expression because it forces
// register spill to stack

... then I think one is going to far, I agree.

That is a good example of something that will be completely
different on x86, x86-64 and IA-64 due to different number
of registers.

Arne
 
Peter said:
Jesse McGrew said:
Peter said:
That last subtle distinction is why discussing these things in a newsgroup is
much more effective than merely reading books. I have a very good 1,000 page
book that never bothers to mention this distinction. In any case it would
still
seem that adding an [in] parameter qualifier might be an improvement.

I don't see the advantage. If you leave the qualifiers off, the
parameter is already "in" by default. Optimizations like the one you're

Its pass by value, which is not the same thing as "in" by default. My suggestion
is to make [in] pass by address, and read-only exactly equivalent to:
ReturnType (const ValueType&, VariableName) // C++
proposing can just as well be handled by the CLR detecting that a large
value-type parameter is never modified, and deciding internally to pass
it by reference instead of copying. Adding an extra language keyword to

Is it read-only? If its not read-only, then its not the same.

Correct: it's not the same, it's better.

Making the parameter read-only is a pointless restriction on the
programmer. The need for it to be read-only is a side effect of the
fact that it's being passed by reference. But the CLR can already
detect whether the parameter is, in fact, modified within the method,
and simply pass value types by reference to the methods where they
aren't modified. Sometimes you need to modify a parameter, and
sometimes you don't; by leaving the optimization up to the CLR, you can
automatically get the benefits when possible without having to change
your code.

Jesse
 
Peter said:
Ignacio Machin ( .NET/ C# MVP ) said:
Generics simply offer the mechanisn for you not to be forced to use a
"cover all instances type" type when you declare a class. [...]
But boxing/unboxing will still be there, forever and ever :)
I don't think so.

Well, boxing certainly won't be removed from .NET, for the obvious
practical reason that a ton of code already depends on it, and so does
much of the OOP design philosophy of .NET. All types derive from
System.Object, and the only way to do that without boxing would be to
make all types into reference types, which would kill performance.

Generics don't eliminate the need for, or usefulness of, boxing. Boxing
is necessary when you need to fit arbitrary values into one type;
generics eliminate some of those cases by constraining the type
automatically, but there are still times when generics are impractical
or don't help at all.

For example, the Tag property of visual controls is an object property,
so it can store a string, an integer, an instance of your own class,
etc., depending on how you want to use that particular control. Doing
that with generics would mean specializing each control class for each
possible tag type - you'd have Button<int> whose Tag property is an
integer, Button<string> to hold strings, etc... and even then, you'd be
limiting the usefulness of the class, because today the very same
button instance can hold an int one minute and a string the next.

Another example: the reflection methods to invoke a method dynamically
from a MethodInfo. You pass in the parameters as object[], which means
any value type parameters have to be boxed. How would you do that with
generics? Every element of the array has to have the same type, but the
method probably doesn't use the same type for each parameter. You might
think about replacing the single invocation method with a tedious
series of generic methods:

Invoke<A>(MethodInfo mi, A arg1)
Invoke<A,B>(MethodInfo mi, A arg1, B arg2)
Invoke<A,B,C>(MethodInfo mi, A arg1, B arg2, C arg3)
and so on

.... but that introduces a number of problems: (1) you'd be limiting the
number of parameters you can pass to the method, because no matter how
many different versions of Invoke you write, each one still only has a
finite number of parameters; (2) you'd need to know the number of
parameters at compile time, whereas today the number of parameters is
determined at runtime by the length of the array you pass in; (3) you'd
complicate any code surrounding a call to Invoke, and probably
complicate Invoke itself, and certainly waste a lot of memory storing
all the different forms of the Invoke method and their specializations.

Jesse
 
Jesse McGrew said:
Peter said:
Jesse McGrew said:
Peter Olcott wrote:
That last subtle distinction is why discussing these things in a newsgroup
is
much more effective than merely reading books. I have a very good 1,000
page
book that never bothers to mention this distinction. In any case it would
still
seem that adding an [in] parameter qualifier might be an improvement.

I don't see the advantage. If you leave the qualifiers off, the
parameter is already "in" by default. Optimizations like the one you're

Its pass by value, which is not the same thing as "in" by default. My
suggestion
is to make [in] pass by address, and read-only exactly equivalent to:
ReturnType (const ValueType&, VariableName) // C++
proposing can just as well be handled by the CLR detecting that a large
value-type parameter is never modified, and deciding internally to pass
it by reference instead of copying. Adding an extra language keyword to

Is it read-only? If its not read-only, then its not the same.

Correct: it's not the same, it's better.

Making the parameter read-only is a pointless restriction on the
programmer.

If this statement was true, then C++ would have never added [const], since C++
did add [const] therefore this statement is not true.
 
Jesse McGrew said:
Peter said:
Ignacio Machin ( .NET/ C# MVP ) said:
Generics simply offer the mechanisn for you not to be forced to use a
"cover all instances type" type when you declare a class. [...]
But boxing/unboxing will still be there, forever and ever :)
I don't think so.

Well, boxing certainly won't be removed from .NET, for the obvious
practical reason that a ton of code already depends on it, and so does
much of the OOP design philosophy of .NET. All types derive from
System.Object, and the only way to do that without boxing would be to
make all types into reference types, which would kill performance.

Generics don't eliminate the need for, or usefulness of, boxing. Boxing
is necessary when you need to fit arbitrary values into one type;
generics eliminate some of those cases by constraining the type
automatically, but there are still times when generics are impractical
or don't help at all.

For example, the Tag property of visual controls is an object property,
so it can store a string, an integer, an instance of your own class,
etc., depending on how you want to use that particular control. Doing
that with generics would mean specializing each control class for each
possible tag type - you'd have Button<int> whose Tag property is an
integer, Button<string> to hold strings, etc... and even then, you'd be
limiting the usefulness of the class, because today the very same
button instance can hold an int one minute and a string the next.

Another example: the reflection methods to invoke a method dynamically
from a MethodInfo. You pass in the parameters as object[], which means
any value type parameters have to be boxed. How would you do that with
generics? Every element of the array has to have the same type, but the
method probably doesn't use the same type for each parameter. You might
think about replacing the single invocation method with a tedious
series of generic methods:

Invoke<A>(MethodInfo mi, A arg1)
Invoke<A,B>(MethodInfo mi, A arg1, B arg2)
Invoke<A,B,C>(MethodInfo mi, A arg1, B arg2, C arg3)
and so on

... but that introduces a number of problems: (1) you'd be limiting the
number of parameters you can pass to the method, because no matter how
many different versions of Invoke you write, each one still only has a
finite number of parameters; (2) you'd need to know the number of
parameters at compile time, whereas today the number of parameters is
determined at runtime by the length of the array you pass in; (3) you'd
complicate any code surrounding a call to Invoke, and probably
complicate Invoke itself, and certainly waste a lot of memory storing
all the different forms of the Invoke method and their specializations.

Jesse
Ah so the boxing and unboxing overhead that does not cost very much adds a lot
of versatility to the underlying functionality while maintaining type safety. It
is comparable to the slight extra overhead that polymorphism requires yet
providing much more versatile code.
 
Peter said:
Making the parameter read-only is a pointless restriction on the
programmer.

If this statement was true, then C++ would have never added [const], since C++
did add [const] therefore this statement is not true.

C++ is not C#. C++ was not designed to run on a virtual machine capable
of reading class definitions and method bodies at runtime and
automatically deducing which optimizations can be performed safely. C#
was, and this is the kind of optimization the CLR can theoretically
perform (even if it doesn't already) without any input from the
programmer.

Why should the programmer have to change his code just to enable an
optimization? Why not just say "your methods will run faster if you
don't modify large value-type parameters"?

Jesse
 
Jesse McGrew said:
Peter said:
Making the parameter read-only is a pointless restriction on the
programmer.

If this statement was true, then C++ would have never added [const], since
C++
did add [const] therefore this statement is not true.

C++ is not C#. C++ was not designed to run on a virtual machine capable
of reading class definitions and method bodies at runtime and
automatically deducing which optimizations can be performed safely. C#
was, and this is the kind of optimization the CLR can theoretically
perform (even if it doesn't already) without any input from the
programmer.

Why should the programmer have to change his code just to enable an
optimization? Why not just say "your methods will run faster if you
don't modify large value-type parameters"?

Jesse

This aspect is not a matter of optimization, it is a matter of preventing
programming errors. By using the [const] parameter qualifier it is impossible to
inadvertently change a function parameter that was not intended to be changed.
 

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

Back
Top