inheritance

  • Thread starter alexey.sviridov
  • Start date
K

Kevin Spencer

All types are not. All classes are. That is because all classes have the
same underlying properties at their core. It is a principle of OOP
(inheritance).

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Numbskull

Show me your certification without works,
and I'll show my certification
*by* my works.
 
K

Kevin Spencer

Let me put it first in terms NOT .Net: A square is a rectangle, but a
rectangle is not necessarily a square. A rectangle is only a square if all
of its sides are of the same length. Similarly, a class is a type, but a
type is not necessarily a class. Value types, such as integers,
enumerations, and structs, are not classes.

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Numbskull

Show me your certification without works,
and I'll show my certification
*by* my works.
 
G

Guest

well let me make sure I clearly understand your point:

I am quoting following lines from .net Components Book from Juval Lowy Page:
544

"The abstract class Type, defined in the System namespace, is an abstraction
of a .NET CLR type. Every .NET type, be it a .NET-provided type(from value
types such as integers and enums to classes and interfaces) or a
developer-defined type, has a corresponding unique Type value.

The canonical base class of any .NET type is System.Object. ..."

If I am understanding it right, you mentioned in your second posting, "All
types are not. All classes are." to the original question "whay all types in
..net are inherited from System.Object ?"

If we look at MSDN it shows
(http://msdn.microsoft.com/library/d...-us/cpref/html/frlrfsystemint32classtopic.asp) it shows:
System.Object
System.ValueType
System.Int32

By looking at the above text, how would you define the relationship between
System.Object->System.ValueType->System.Int32 ?
 
K

Kevin Spencer

The word "type" is a general term which indicates a definition of the most
basic characteristics of binary data. All data and code in a computer is
binary, meaning that it is 1 or more 1's and 0's. In order for the computer
to work with data, it needs to know something about the basic definition of
the data. What is the difference between 10001011 and 10001011? Well, both
are 8-bits in size, and both have 1's and 0's in the same order and
position. However, depending upon the data type they represent, they can
represent any of several different "types" of data. For example, one might
represent an unsigned byte, and one might represent a signed byte (a byte is
8 bits of data). A signed byte uses the 8th bit to represent the sign
(positive or negative), and can therefore store only half the value of an
unsigned bit, bit either positive or negative, while an unsigned byte can
not represent a negative number. One might represent a number, while the
other represents a character.

The type of the data tells the computer how to work with it, what size it is
(all data in a computer is consecutive), and the like.

Of course, as time has gone by, the word "type" has grown in scope, but
remains the same basic principle.
I am quoting following lines from .net Components Book from Juval Lowy
Page:
544

"The abstract class Type, defined in the System namespace, is an
abstraction
of a .NET CLR type. Every .NET type, be it a .NET-provided type(from value
types such as integers and enums to classes and interfaces) or a
developer-defined type, has a corresponding unique Type value.

The canonical base class of any .NET type is System.Object. ..."
If I am understanding it right, you mentioned in your second posting, "All
types are not. All classes are." to the original question "whay all types
in
.net are inherited from System.Object ?"

I can understand your confusion. In one way, value types are indeed
inherited from System.Object, in that in the CLR, all value types are
classes derived from System.ValueType. However, in another sense, they are
not objects in that the underlying object is not used unless it is needed,
and then is converted to an object type by virtue of Boxing and Unboxing.

In other words, when you create an integer, like so:

int i = 10;

The actual space allocated on the stack for "i" is 32 bits, the space needed
to store the "naked" integer. At this point, the data itself is not a class;
it is a literal integer. However, when you treat it like System.Int32, by
using any of the class properties, it is "boxed" into an instance of the
System.Int32 class.

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Numbskull

Show me your certification without works,
and I'll show my certification
*by* my works.
 
A

arifkhan2

Kevin, thanks for your detailed response, regarding boxing of "naked"
integer, can you please clarify in the following code when exactly a
literal integer will be boxed into an instance? Exactly speaking do you
think calling GetHashCode or ToString on a declared "naked" integer
will cause it to box? or only by specifically casting it to an object
will box it ?

class abc
{

function void TestInteger()
{
int a;
a = 10; //literal or naked integer

int b = a.GetHashCode(); // Will 'a' be Boxed or remain naked integer ?
string c = a.ToString(); // Will 'a' be Boxed or remain naked integer ?

object o = (object) i; //Will be boxed.
}
}
 
K

Kevin Spencer

You're quite welcome. This stuff can be confusing.
int a;
a = 10; //literal or naked integer

As long as you treat the variable "a" as if it were an integer, it will
remain unboxed, as in these 2 cases.
int b = a.GetHashCode(); // Will 'a' be Boxed or remain naked integer ?
string c = a.ToString(); // Will 'a' be Boxed or remain naked integer ?

object o = (object) i; //Will be boxed.

In these cases, you are calling a method of the System.Int32 class, in which
case the variable is boxed as an instance of the System.Int32 class.

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Numbskull

Show me your certification without works,
and I'll show my certification
*by* my works.
 
J

Jon Skeet [C# MVP]

Kevin Spencer said:
You're quite welcome. This stuff can be confusing.

Apparently so ;)
As long as you treat the variable "a" as if it were an integer, it will
remain unboxed, as in these 2 cases.


In these cases, you are calling a method of the System.Int32 class, in which
case the variable is boxed as an instance of the System.Int32 class.

System.Int32 isn't a class, it's a struct.

Neither the call to GetHashCode nor the call to ToString results in a
box operation, as can be easily verified with ildasm.

The cast to object, however, *does* involve a box.


It gets more confusing though when talking about other value types
which *don't* override GetHashCode and ToString themselves. Consider
the following code:

using System;

struct Foo
{
}

class Test
{
static void Main()
{
Foo a = new Foo();

int b = a.GetHashCode();
string c = a.ToString();

object o = (object) a;
}
}

In C# 1.1, the calls to GetHashCode and ToString both involve a boxing
operation. In C# 2.0, however, the "constrained." IL prefix is used,
which avoids a box.
 
K

Kevin Spencer

Hi Jon,

I certainly did step on the class/struct thing. In too much of a hurry, I'm
afraid. I did know that Int32 is a struct, but got sloppy. Been putting in
too many hours lately.

As for the boxing explanation, I did not realize that. I was certain that
GetHashCode or ToString would result in a boxing operation, because they are
both methods of System.Object, and they are listed in the SDK as being
overridden. The assumption I made was that they override the System.Object
methods, rather than the System.ValueType methods.

Thanks for the ...clarification?

--
;-),

Kevin Spencer
Microsoft MVP
Professional Numbskull

Show me your certification without works,
and I'll show my certification
*by* my works.
 
J

Jon Skeet [C# MVP]

Kevin Spencer said:
I certainly did step on the class/struct thing. In too much of a hurry, I'm
afraid. I did know that Int32 is a struct, but got sloppy. Been putting in
too many hours lately.
:)

As for the boxing explanation, I did not realize that. I was certain that
GetHashCode or ToString would result in a boxing operation, because they are
both methods of System.Object, and they are listed in the SDK as being
overridden. The assumption I made was that they override the System.Object
methods, rather than the System.ValueType methods.

Thanks for the ...clarification?

I have to say, the business about the "constraint" part of C# 2.0 to
avoid even virtual non-overridden methods from involving boxing was a
surprise to me. I end up learning something virtually every time I use
ildasm :)

The methods do indeed override the System.Object methods, but I think
the point is that because the compiler (even in 1.1) knows exactly
which method is going to be called - as structs are sealed, the method
can't be overridden any further - there's no need to box.
 
K

Kevin Spencer

Well, Jon, keep on sharing what you've learned! Aside from the copious and
varied research I must do on a daily basis in order to do my job, my time in
these newsgroups tends to fill in some of the remaining gaps in my
understanding, one way or another, and I always enjoy your insights into the
lower levels of the .Net technology, which I often don't have enough time to
research as thoroughly as I would like to otherwise (unfortunately, I can
only go without so much sleep!). When I participate here, I can contribute
what I know, as well as learning something new from time to time, which are
both worth my time.

--

Kevin Spencer
Microsoft MVP
Professional Numbskull

Show me your certification without works,
and I'll show my certification
*by* my works.
 
J

Jon Skeet [C# MVP]

Kevin Spencer said:
Well, Jon, keep on sharing what you've learned! Aside from the copious and
varied research I must do on a daily basis in order to do my job, my time in
these newsgroups tends to fill in some of the remaining gaps in my
understanding, one way or another, and I always enjoy your insights into the
lower levels of the .Net technology, which I often don't have enough time to
research as thoroughly as I would like to otherwise (unfortunately, I can
only go without so much sleep!). When I participate here, I can contribute
what I know, as well as learning something new from time to time, which are
both worth my time.

Likewise. While I enjoy helping others, I'm not so altruistic that I
would spend all this time on the newsgroups if I wasn't learning
something too :)

In fact, virtually everything I know about C#/.NET has been due to the
newsgroups in one form or another. I've always found that a great way
of learning your way around a new language/platform/whatever is to try
to answer the problems that other people have - if they have them,
chances are you'll have them too at some stage :)

(Another thing to do to find nooks and crannies is to read the specs.
I've recently been reading the C# 2.0 draft ECMA specs from start to
end, and there are all kinds of things I never knew about. Have you
ever seen people overloading the true and false operators, for
instance?)
 
K

Kevin Spencer

Hi Jon,
(Another thing to do to find nooks and crannies is to read the specs.
I've recently been reading the C# 2.0 draft ECMA specs from start to
end, and there are all kinds of things I never knew about. Have you
ever seen people overloading the true and false operators, for
instance?)

I do that too, when I need some information, or have the time. I have the
ECMA spec for C#, but have not had time to read it end to end, although it
makes fascinating reading. I'm also learning some advanced math in the same
way, but, for example, I have several books, and only read a few pages at a
time when I'm at the doctor's office or something!

Part of my problem is that I have so many interests that are related to
programming, I have to divide my free time among them!

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Numbskull

Show me your certification without works,
and I'll show my certification
*by* my works.

news:[email protected]...
 
A

arifkhan2

So to conclude this discussion on boxing of 'Int', here are the
conclusions that I am deriving form our dicussion. Please correct me if
I am wrong.

1. Calling GetHashCode(), GetTypeCode or ToString() on an 'int' will
NOT cause it to be boxed.

int c = i.GetHashCode(); //No Box
TypeCode tc = i.GetTypeCode(); //No Box
string str = i.ToString(); //No Box


2. Calling GetType() on int variable or specifically casting an 'int'
to an object will cause it to be boxed.

Type t = i.GetType(); //Box
object o = (object) i; //Box

3. In case of non-boxed operation on an 'int'( which being struct is
nothing but a sealed class), compiler basically calls
System.Int32::(corresponding operation) e.g.
System.Int32::GetHashCode().

In addition to the discussion following program and corresponding IL
code help to derive the above conclusions. Thanks Arif

////////////////Sample Code////////////////

class Program
{
static void Main(string[] args)
{
IntegerTest();
}

static void IntegerTest()
{
int i;
i = 20;
int c = i.GetHashCode(); //No Box
Type t = i.GetType(); //Box
TypeCode tc = i.GetTypeCode(); //NoBox
string str = i.ToString(); //No Box
Console.WriteLine(c);
object o = (object) i; //Box
c = o.GetHashCode();
t = o.GetType();
str = o.ToString();
Console.WriteLine(c);
}
}


////////////////Corresponding IL code//////////////////
..method private hidebysig static void IntegerTest() cil managed
{
// Code size 86 (0x56)
.maxstack 1
.locals init ([0] int32 i,
[1] int32 c,
[2] class [mscorlib]System.Type t,
[3] valuetype [mscorlib]System.TypeCode tc,
[4] string str,
[5] object o)
IL_0000: ldc.i4.s 20
IL_0002: stloc.0
IL_0003: ldloca.s i
IL_0005: call instance int32
[mscorlib]System.Int32::GetHashCode()
IL_000a: stloc.1
IL_000b: ldloc.0
IL_000c: box [mscorlib]System.Int32
IL_0011: call instance class [mscorlib]System.Type
[mscorlib]System.Object::GetType()
IL_0016: stloc.2
IL_0017: ldloca.s i
IL_0019: call instance valuetype [mscorlib]System.TypeCode
[mscorlib]System.Int32::GetTypeCode()
IL_001e: stloc.3
IL_001f: ldloca.s i
IL_0021: call instance string
[mscorlib]System.Int32::ToString()
IL_0026: stloc.s str
IL_0028: ldloc.1
IL_0029: call void [mscorlib]System.Console::WriteLine(int32)
IL_002e: ldloc.0
IL_002f: box [mscorlib]System.Int32
IL_0034: stloc.s o
IL_0036: ldloc.s o
IL_0038: callvirt instance int32
[mscorlib]System.Object::GetHashCode()
IL_003d: stloc.1
IL_003e: ldloc.s o
IL_0040: callvirt instance class [mscorlib]System.Type
[mscorlib]System.Object::GetType()
IL_0045: stloc.2
IL_0046: ldloc.s o
IL_0048: callvirt instance string
[mscorlib]System.Object::ToString()
IL_004d: stloc.s str
IL_004f: ldloc.1
IL_0050: call void [mscorlib]System.Console::WriteLine(int32)
IL_0055: ret
} // end of method Program::IntegerTest
 
J

Jon Skeet [C# MVP]

So to conclude this discussion on boxing of 'Int', here are the
conclusions that I am deriving form our dicussion. Please correct me if
I am wrong.

1. Calling GetHashCode(), GetTypeCode or ToString() on an 'int' will
NOT cause it to be boxed.
Correct.

2. Calling GetType() on int variable or specifically casting an 'int'
to an object will cause it to be boxed.

Type t = i.GetType(); //Box
object o = (object) i; //Box

Yes. I'm not sure why the C# 2.0 compiler can't use the "constraint"
prefix for the call to GetType, but it appears not to.
3. In case of non-boxed operation on an 'int'( which being struct is
nothing but a sealed class),

Well, a sealed type - it's not a class.
compiler basically calls
System.Int32::(corresponding operation) e.g.
System.Int32::GetHashCode().

Yes.
 
A

arifkhan2

Regarding int being "Well, a sealed type - it's not a class. ":

When I look at IL of mscorlib.dll for Int32, the first line it shows
is:

Int32
.class value public sequential ansi serializable sealed
beforefieldinit

Although i understand that saying it a type is not wrong becuase
integer, enum, classes, interfaces etc in .net terms are all types but
do you think being specific about struct and saying it a sealed class
is wrong?

Please correct me if I am wrong in saying that System.Int32 (struct) is
a sealed class which inherits from System.ValueType class and which
inherits from System.Object class.

Thanks Arif
 
J

Jon Skeet [C# MVP]

Regarding int being "Well, a sealed type - it's not a class. ":

When I look at IL of mscorlib.dll for Int32, the first line it shows
is:

Int32
.class value public sequential ansi serializable sealed
beforefieldinit

Although i understand that saying it a type is not wrong becuase
integer, enum, classes, interfaces etc in .net terms are all types but
do you think being specific about struct and saying it a sealed class
is wrong?

Yes, I'm afraid I think so. I'll admit having checked the CLI spec that
it's less clear than I expected though.
Please correct me if I am wrong in saying that System.Int32 (struct) is
a sealed class which inherits from System.ValueType class and which
inherits from System.Object class.

Hmm. It's unfortunate that IL uses ".class" when it doesn't necessarily
mean a class, but any type. From the ECMA spec:

<quote>
Rationale: For historical reasons, many of the syntactic classes used
for defining types incorrectly use =3Fclass=3F instead of =3Ftype=3F in their
name. All classes are types, but =3Ftypes=3F is a broader term encompassing
value types, and interfaces.
</quote>

And also:

<quote>
Types (i.e., classes, value types, and interfaces) may be defined at
the top-level of a module:
</quote>

That specifically distinguishes between classes and value types.

On the other hand, other bits of the spec use "class type" to value
types. It looks like depending on what you read, it's possible that a
value type is a class type but not a class. The important thing (IMO)
is that the normal connotation of "class" is "reference type", which
System.Int32 (in its unboxed form) certainly isn't. Calling
System.Int32 a class is, I *believe*, strictly incorrect (although
"class type" would have been correct, apparently). Incorrect or not,
however, I believe it's misleading. (I'm not saying this was deliberate
for a second, by the way!)


Now, as for System.Int32 inheriting from System.ValueType - the value
type doesn't inherit from anything, but the boxed type inherits from
System.ValueType - to be *hugely* pedantic, again taking stuff from the
spec.

The CIL spec certainly doesn't go out of its way to make any of this
easier for us, does it?
 
A

arifkhan2

The CIL spec certainly doesn't go out of its way to make any of thisI agree it does not. I think CIL using .class for Int32 definitely
makes it confusing. Thanks for your help in clarifying this issue.

Regards, Arif
 

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