Home All Groups Group Topic Archive Search About

Types system in .NET

Author
14 Jan 2005 6:02 AM
Paul Selormey
There is many things in the design of the .NET type system
I do not understand why it should be like that:

1. Why are we not allowed to provide parameterless constructors
    for value types? (I find it a large limitation, since I sometimes
    need defaults/initialization other than the process provides)

2. Why is the ValueType derived from Object?

3. Since the derivation of ValueType from Object, makes it a class
   why boxing?

4. Why is "ValueTypeArray" not provided instead of just Array for
   everything?

5. Why is there no common base ValueType for numerics/numbers?

I recently found myself writing a class like,
public class TestClass
{
    private ValueType m_valueMax;

public TestClass(ValueType value)
{
        m_valueMax = value;
}

    public ValueType Value
    {
        get
        {
            return m_valueMax;
        }
    }
}

instead of
public class TestClass
{
    private object m_valueMax;

public TestClass(object value)
{
        m_valueMax = value;
}

    public object Value
    {
        get
        {
            return m_valueMax;
        }
    }
}

because I simply needed a number to be passed it, and do not
need to be doing stuff like

if (value == null)
    throw new ArgumentNullException("value");

Best regards,
Paul.

Author
14 Jan 2005 6:55 AM
Jon Skeet [C# MVP]
Paul Selormey <p***@toolscenter.org> wrote:
> There is many things in the design of the .NET type system
> I do not understand why it should be like that:
>
> 1. Why are we not allowed to provide parameterless constructors
>     for value types? (I find it a large limitation, since I sometimes
>     need defaults/initialization other than the process provides)

In some circumstances (such as array creation) you'd either have to
take a huge performance hit, executing every constructor (when often
you'd then want to write over the top of the array anyway) or you'd
have to accept that the constructor wasn't always called. I think this
would lead to confusion.

> 2. Why is the ValueType derived from Object?

Because all classes do, however...

> 3. Since the derivation of ValueType from Object, makes it a class
>    why boxing?

ValueType is indeed a reference type. However, things get tricky - the
types derived from ValueType are *actually* reference types, but
they're only the boxed types. The value types themselves are types with
the same name, but which don't actually derive from anything. It's all
a bit strange, but it's explained in the CLI spec.

> 4. Why is "ValueTypeArray" not provided instead of just Array for
>    everything?

What help would it be?

> 5. Why is there no common base ValueType for numerics/numbers?

As value types can't inherit from anything other than ValueType, that
would be hard. An interface might be useful, but only in some
situations.

<snip>

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Author
14 Jan 2005 7:42 AM
Paul Selormey
Hello Jon,
Thanks for the response.

>> There is many things in the design of the .NET type system
>> I do not understand why it should be like that:
>>
>> 1. Why are we not allowed to provide parameterless constructors
>>     for value types? (I find it a large limitation, since I sometimes
>>     need defaults/initialization other than the process provides)
>
> In some circumstances (such as array creation) you'd either have to
> take a huge performance hit, executing every constructor (when often
> you'd then want to write over the top of the array anyway) or you'd
> have to accept that the constructor wasn't always called. I think this
> would lead to confusion.

Nice explanation, there is at least a reason :-)

"In some circumstances", should be easy then. If the user provides the
parameterless constructor you use it, if not there is nothing there anyway!

>> 2. Why is the ValueType derived from Object?
>
> Because all classes do, however...

I think this does explain anything...

>> 3. Since the derivation of ValueType from Object, makes it a class
>>    why boxing?
>
> ValueType is indeed a reference type. However, things get tricky - the
> types derived from ValueType are *actually* reference types, but
> they're only the boxed types. The value types themselves are types with
> the same name, but which don't actually derive from anything. It's all
> a bit strange, but it's explained in the CLI spec.

I might have to look into the CLI spec to see the picture, since I still do
not
see the need for this strange step.

It is even getting stranger with coming .NET 2.0's null structures. Why not
simply provide a IsNull method in the ValueType, which can be overriden
like the Equals method?

>> 4. Why is "ValueTypeArray" not provided instead of just Array for
>>    everything?
>
> What help would it be?

If that might avoid boxing. I might boxing if I write?

ValueType dValue = 2.0d;

In a project, I had to create DoubleCollection, IntegerCollection etc.

>> 5. Why is there no common base ValueType for numerics/numbers?
>
> As value types can't inherit from anything other than ValueType, that
> would be hard. An interface might be useful, but only in some
> situations.

We still have a special value type the "System.Enum", which even permits us
to
write (in C#)

public System.Enum N : short
{
}

so why not System.Number?
That could then give rise! to

public System.Double : System.Number
{
}

An interface will not be appropriate since we will then be dealing with
boxing issues again.

Best regards,
Paul.
Author
16 Jan 2005 9:49 PM
Jon Skeet [C# MVP]
Paul Selormey <p***@toolscenter.org> wrote:
> > In some circumstances (such as array creation) you'd either have to
> > take a huge performance hit, executing every constructor (when often
> > you'd then want to write over the top of the array anyway) or you'd
> > have to accept that the constructor wasn't always called. I think this
> > would lead to confusion.
>
> Nice explanation, there is at least a reason :-)
>
> "In some circumstances", should be easy then. If the user provides the
> parameterless constructor you use it, if not there is nothing there anyway!

But that forces all users of your struct to pay a performance penalty
every time they create an array - nasty.

<snip>

> > ValueType is indeed a reference type. However, things get tricky - the
> > types derived from ValueType are *actually* reference types, but
> > they're only the boxed types. The value types themselves are types with
> > the same name, but which don't actually derive from anything. It's all
> > a bit strange, but it's explained in the CLI spec.
>
> I might have to look into the CLI spec to see the picture, since I still do
> not see the need for this strange step.
>
> It is even getting stranger with coming .NET 2.0's null structures. Why not
> simply provide a IsNull method in the ValueType, which can be overriden
> like the Equals method?

Because that being available would imply the need for extra space for
*every* value type. The ability to have an extra value (null) doesn't
come for free. It's also good to be able to express which values need
to potentially be treated specially.

> >> 4. Why is "ValueTypeArray" not provided instead of just Array for
> >>    everything?
> >
> > What help would it be?
>
> If that might avoid boxing. I might boxing if I write?
>
> ValueType dValue = 2.0d;

That's definitely boxing.

> In a project, I had to create DoubleCollection, IntegerCollection etc.

That will be solved by generics, of course. However, without generics
you'd have a major problem - double is a different size from int (just
one example), so you couldn't possibly declare a variable to be of
"general value type" without either wasting loads of space or
restricting the values to only be those of a certain maximum size,
neither of which is very palatable.

Show quote
> >> 5. Why is there no common base ValueType for numerics/numbers?
> >
> > As value types can't inherit from anything other than ValueType, that
> > would be hard. An interface might be useful, but only in some
> > situations.
>
> We still have a special value type the "System.Enum", which even permits us
> to write (in C#)
>
> public System.Enum N : short
> {
> }
>
> so why not System.Number?

That's C# syntax, but it doesn't *actually* make the enum derive from
short.

<snip>

Value types don't come with type information - just the value - so if
you declares something as being just "Number" there'd be no way of
knowing either how much space that variable should take up, or (after
allocating a value to it) what type the value should actually be.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Author
14 Jan 2005 3:56 PM
Sean Hederman
"Paul Selormey" <p***@toolscenter.org> wrote in message
news:OsbRn4f%23EHA.4072@TK2MSFTNGP10.phx.gbl...
> There is many things in the design of the .NET type system
> I do not understand why it should be like that:
>
> 1. Why are we not allowed to provide parameterless constructors for value
> types? (I find it a large limitation, since I sometimes
>    need defaults/initialization other than the process provides)

The CLR actually does allow for parameterless (default) constructors, but C#
doesn't. If you have a look at the generated IL of structs and classes
(without constructors), you'll see that the C# compiler generates a default
constructor for classes, but not for structs. The C# compiler initializes
structs not by a default constructor but by setting all value type fields to
their default values, and all reference type fields to null (using the
..initobj IL instruction). So initializing a struct like this:
MyStruct a = new MyStruct();
would not call a default constructor (if it could have one), but would use
the .initobj instruction instead.

As to why this is so, read
http://www.dotnetconsult.co.uk/weblog/PermaLink.aspx/03805a0c-525f-4b7d-b0a0-f5f2773b4a7c
for more detail. basically it boils down to array initialization. If you
declare an array of 20 Foo's, then the system has to allocate memory for
that on the stack. For reference types this is easy, it just allocates 20
null references (which will later each point to the heap). However, a value
type is stored in the stack, right inside the array. That would mean that it
would have to create 20 structs, and call each one's default constructor. If
the constructor did something expensive and we change 20 to 20,000 you
suddenly have a major performance problem.

The point to remember about value types is that you're sacrificing a bit of
flexibility in return for large performance improvements.

> 2. Why is the ValueType derived from Object?

It provides a unified type system. Absolutely everything can be cast to
Object from which you can do a whole bunch of funky stuff.

> 3. Since the derivation of ValueType from Object, makes it a class
>   why boxing?

Whilst ValueType is inherited from Object, a value type is NOT. It is a
standard primitive much as you get in any other programming environment.
However you can use it as if it were inherited from Object. When you do this
however, the underlying value type is boxed, and all of a sudden appears to
inherit from Object.

> 4. Why is "ValueTypeArray" not provided instead of just Array for
>   everything?

It would be quite a pain to have two different array types. Either they'd
have to be completely unrelated, or they'd have to inherit from a common
interface. Said interface would HAVE to use Object params to be common
across both value and reference types, and therefore you'd still have boxing
occurring. In addition as I noted above, many value types (maybe all?) are
not actually derived from ValueType, and only appear to do so after a boxing
operation. So having a method like:
void Add(ValueType value)
will result in a boxing operation when you call it.

This issue is the cause of quite a few performance hits in the framework.
Luckily for us, generics will make many of these disappear like the morning
dew.

> 5. Why is there no common base ValueType for numerics/numbers?
[snip example]
The different number types are fairly disparate beasts. There's not one
method on Int32 for example that I can see that one could port to another
numeric type in a generic manner. So you'd have a base class with no methods
or properties. If the only thing the base class is adding is type
discrimination, then it's just overhead.

Why don't you rather have the following constructors:
public TestClass(int value){}
public TestClass(float value){}
public TestClass(double value {}
etcetera, etcetera

AddThis Social Bookmark Button