8

Can a struct be derived from a class in c#?

If not, Why can primitive data types, such as int, be derived from the class object? Since the data type int is basically a struct type(value type).

Is this just an exception to the rule?

Ryan Gates
  • 4,501
  • 6
  • 50
  • 90
  • 1
    There are many things within the language that are done by the compiler (or at an even lower level than that) but that you yourself can't do. This is one such example. – Servy Dec 04 '12 at 17:08
  • @Servy: Actually, that is not quite correct. – SLaks Dec 04 '12 at 17:12
  • so the inheritance i'm talking about is done at a lower level and we as developers are deprived of such rights? This just isn't fair :) – Nithish Inpursuit Ofhappiness Dec 04 '12 at 17:13
  • @SLaks Not correct in that you can actually have a struct derived from an object other than `ValueType`, or incorrect in that you can write C# code to do anything that the language itself can do? – Servy Dec 04 '12 at 17:13
  • 1
    @NithishInpursuitOfhappiness Keep in mind structs can still implement interfaces, which may solve your problem. – Servy Dec 04 '12 at 17:14
  • @NithishInpursuitOfhappiness: No; this is just part of the meaning of a `struct`. – SLaks Dec 04 '12 at 17:14
  • @Servy: Not correct in that `int` is no different from other structs in this regard. – SLaks Dec 04 '12 at 17:14
  • 1
    @SLaks I never intended to say otherwise, not do I see how you get that out of what I said. I was referring to simply defining the super type of any struct as something you don't control, but I also had a number of other unrelated things in mind which are special cased by the compiler/runtime and couldn't be implemented through plain C# code. – Servy Dec 04 '12 at 17:17
  • possible duplicate of http://stackoverflow.com/questions/1222935/why-dont-structs-support-inheritance – Christian Westman Dec 04 '12 at 17:18
  • @Christian I know that a struct doesn't support inheritance. I'm just keen about the exception that we're discussing – Nithish Inpursuit Ofhappiness Dec 04 '12 at 17:20

4 Answers4

9

Integers and other value types (e.g. bool) are objects, because it allows them to leverage inheritance (i.e. they have access to the common .Equals(), .GetType(), .ToString() functions).

It's a design decision in the .NET framework. Rather than writing separate functions for all the value types under System.ValueType, they use a common code base.

Microsof's document on Types

mmmmmm
  • 32,227
  • 27
  • 88
  • 117
Alexander Matusiak
  • 1,748
  • 2
  • 18
  • 29
  • So struct cannot be extended from a class! The language has the one exception to have access to methods like .Equals(). This helps :) – Nithish Inpursuit Ofhappiness Dec 04 '12 at 17:24
  • 2
    @NithishInpursuitOfhappiness No, actually `System.ValueType` **is** a class, and so all structs **must** derive from a class, namely the class `System.ValueType`. But it is not allowed to derive from _another_ class than `System.ValueType`. And it is not even allowed to specify your base class (it must be "automatic" `System.ValueType`). The class `System.ValueType` derives from `System.Object`. This is the reason why your struct inherits all the members of `System.Object`. And the same with `int`: It is a struct, and it derives from the class `System.ValueType`. – Jeppe Stig Nielsen Dec 17 '12 at 15:49
6

All structs inherit System.ValueType, which in turn inherits Object.

You cannot change that.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
1

When the run-time allocates a storage location for a type, or generates code to operate on one, it checks whether the type derives from System.ValueType but is not System.ValueType itself. Unless the storage location meets those criteria, it will hold a heap object reference, and any code to operate on its members (fields, methods, properties, etc.) will act upon the referenced object. Otherwise, the storage location will hold all the public and private fields of that type (which will be laid out identically in all storage locations of that type), and any code to operate on its members will operate on the storage location itself.

If an attempt is made to store a value type into a storage location of class ValueType, or a storage location which does not derive from ValueType, the system will generate a new heap object of the storage location's type, and then store a reference to that object in the appropriate storage location. Although storage locations of types deriving from System.ValueType, and code to access them, are treated specially by the run-time, heap object instances which inherit from System.ValueType (such as the newly-created one just mentioned) are simply heap objects that happen to derive from System.ValueType, and have inheritance behaviors which are essentially the same as other types, and may thus be passed around by code expecting to deal with heap references.

A statement like Object Foo = New System.Drawing.Point(3,4); actually involves three kinds of things:

  1. An unnamed temporary storage location of type `System.Drawing.Point(3,4)` which holds the private fields of that type (two integers), and is initialized to (3,4). Note that this storage location does not hold an `Object`; it holds two integers which the compiler knows represent its fields.
  2. A heap object of type `System.Drawing.Point`. Because this is a heap object, it inherits from `System.Object`, as do all heap objects.
  3. A storage location of type `Object`, which is represented by the variable name `Foo`.

The upshot of all this is that while value types may be defined as inheriting from ValueType which inherits from Object, and while heap objects whose types inherit from ValueType do inherit from Object, storage locations of value types do not hold things that inherit from Object.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • You: _it checks whether the type derives from `System.ValueType` but is not `System.ValueType` itself._ Of course, there's also `System.Enum` which is a class deriving from `ValueType`, and if you say `Enum e = DayOfWeek.Thursday;` the same kind of **boxing** takes place. – Jeppe Stig Nielsen Dec 17 '12 at 15:57
  • @JeppeStigNielsen: I hadn't ever seen `System.Enum` used as a type of storage location. I suppose the fact that it works as one explains why one can't use an `Enum` constraint (since constraining something to `Enum` would mean it must either be an enumerated type, or `System.Enum` which behaves nothing like one). I'm impressed in some ways at how well generics were able to work with the "unified type system", but wish value types and enums had separate `Type` objects for boxed and unboxed forms, so one could declare a parameter of e.g. type "boxed `Int32`". – supercat Dec 17 '12 at 17:06
  • Some people use `Enum` like that. The Framework doesn't use it much. However, if you say `BindingFlags bf = XXX; if (bf.HasFlag(BindingFlags.Static)) { /* ... */}`, then the argument is boxed into a `System.Enum` storage location. That method was new in .NET 4.0. – Jeppe Stig Nielsen Dec 17 '12 at 18:08
  • @JeppeStigNielsen: A generic extension method which constrains its parameter as `struct` can run avoid boxing and run 30 times as fast as a method that uses type `System.Enum`. By my understanding, even though C# doesn't provide a means of declaring a type constraint of `System.Enum`, other .net languages allow it. Given that `enum.HasFlag` is something programmers might use a lot, expecting it to be fast (since it's just doing a bitwise-AND on a couple of integers) I wonder why MS didn't write that extension method in a language where it could run quickly. – supercat Dec 17 '12 at 22:36
0

The class hiearchy works as follows (simplified):

Object -> ValueType -> int Object -> ValueType -> struct

Structs by definition of c# do not allow inheritance.

Here is a nice article describing the role of stucts within the C# language:

http://msdn.microsoft.com/en-us/library/aa288471(v=vs.71).aspx

Nathan Tregillus
  • 6,006
  • 3
  • 52
  • 91