|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Types system in .NETI 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. Paul Selormey <p***@toolscenter.org> wrote:
> There is many things in the design of the .NET type system In some circumstances (such as array creation) you'd either have to > 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) 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 ValueType is indeed a reference type. However, things get tricky - the > why boxing? 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 What help would it be?> everything? > 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 Hello Jon,
Thanks for the response. >> There is many things in the design of the .NET type system Nice explanation, there is at least a reason :-)>> 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. "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? I think this does explain anything...> > Because all classes do, however... >> 3. Since the derivation of ValueType from Object, makes it a class I might have to look into the CLI spec to see the picture, since I still do >> 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. 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 If that might avoid boxing. I might boxing if I write?>> everything? > > What help would it be? 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? We still have a special value type the "System.Enum", which even permits us > > 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. 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. Paul Selormey <p***@toolscenter.org> wrote:
> > In some circumstances (such as array creation) you'd either have to But that forces all users of your struct to pay a performance penalty > > 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! every time they create an array - nasty. <snip> > > ValueType is indeed a reference type. However, things get tricky - the Because that being available would imply the need for extra space for > > 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? *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 That's definitely boxing.> >> 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. 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? That's C# syntax, but it doesn't *actually* make the enum derive from > > > > 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? 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 "Paul Selormey" <p***@toolscenter.org> wrote in message The CLR actually does allow for parameterless (default) constructors, but C# 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) 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 Whilst ValueType is inherited from Object, a value type is NOT. It is a > why boxing? 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 It would be quite a pain to have two different array types. Either they'd > everything? 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? The different number types are fairly disparate beasts. There's not one [snip example] 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 |
|||||||||||||||||||||||