Casting in VB.Net and C#

  • Thread starter Thread starter Ken Allen
  • Start date Start date
K

Ken Allen

I am relatively new to .Net, but have been using VB and C/C++ for years.

One of the drawbacks with VB6 and earlier was the difficulty in casting a
'record' to a different 'shape' so one could perform different manipulations
on it. For example, I have a complex data structure, which I can represent
in a VB6 TYPE declaration, but I cannot easily convert that to a fixed
length array of unsigned bytes so that I could perform a checksum
calculation on the contents. Another case is where a read a buffer from a
file and then wish to interpret the contents based on some header
information. This was also very difficult in VB6.

What facilities are available in VB.Met and C# (which does not have
pointers, which made this so easy, albeit error prone, in C and C++)?

-Ken
 
Just to clarify the difference between CType and DirectCast.

DirectCast can only be used on reference types
and they have to be the same type. Whereas, CType
can be used on both Value Types and Reference Types
where the casting is permissable.

DirectCast is faster at runtime than CType.

Regards - OHM#


Jan said:
In VB.NET you can use:
- CType
- DirectCast

In C# you can use:
- (typeName)

Regards - OHM# (e-mail address removed)
 
"One Handed Man [ OHM# ]"
Just to clarify the difference between CType and DirectCast.

DirectCast can only be used on reference types
and they have to be the same type. Whereas, CType
can be used on both Value Types and Reference Types
where the casting is permissable.

Only a remark: DirectCast can also be used with value types when the object
is boxed:

Dim o As Object
Dim i As Integer
o = 17I
i = DirectCast(o, Integer)


@Ken:
DirectCast performs type casting whereas CType can perform type casting
_and_ type conversion. Type casting only changes the type of the reference,
but it does not create a new object. Type conversion does create a new
object.
DirectCast is faster at runtime than CType.

Under which circumstances? I read this also before but I could not reproduce
it. The speed was equal.
 
Ken,
What facilities are available in VB.Met and C# (which does not have
pointers, which made this so easy, albeit error prone, in C and C++)?
Personally that is the key word "error prone"! .NET goes out of its way to
avoid such error prone code!
One of the drawbacks with VB6 and earlier was the difficulty in casting a
'record' to a different 'shape' so one could perform different manipulations
on it.
Luckily VB6 & VB.NET have type safety! I consider this a major benefit not a
drawback!

Note a VB6 Type is a VB.NET Structure, however I would recommend using a
Class instead.
I have a complex data structure, which I can represent
in a VB6 TYPE declaration, but I cannot easily convert that to a fixed
length array of unsigned bytes so that I could perform a checksum
calculation on the contents.
I would "serialize" the structure to a MemoryStream using a BinaryWriter. I
would then calculate the checksum on the MemoryStream. Both MemoryStream &
BinaryWriter are in the System.IO namespace. Alternatively you can use
System.GitConverter.GetBytes to get byte arrays for individual members
however the BinaryWriter & MemoryStream makes this significantly easier!
Another case is where a read a buffer from a
file and then wish to interpret the contents based on some header
information.
I would use an BinaryReader to read the header information interpreting &
"deserializing" as I go. BinaryReader is also in the System.IO namespace.

By "serialize" and "deserialize" I mean I would implement custom routines
that would convert an object to & from a binary format using the
BinaryReader & BinaryWriter classes similar to what is described in the
following article:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp09182003.asp

Note the samples are C#, with your C++ background you should be able to
convert them.

An alternative to the BinaryReader & BinaryWriter is the
System.Runtime.InteropSerivces.Marshal class. Check out the StructureToPtr &
PtrToStructure methods along with the Copy or Read methods. Although the
method is StructureToPtr you can use them with either a VB.NET Class or a
Structure...

Hope this helps
Jay
 
But its primary Type is still Object

Regards - OHM

Armin said:
"One Handed Man [ OHM# ]"
Just to clarify the difference between CType and DirectCast.

DirectCast can only be used on reference types
and they have to be the same type. Whereas, CType
can be used on both Value Types and Reference Types
where the casting is permissable.

Only a remark: DirectCast can also be used with value types when the
object is boxed:

Dim o As Object
Dim i As Integer
o = 17I
i = DirectCast(o, Integer)


@Ken:
DirectCast performs type casting whereas CType can perform type
casting _and_ type conversion. Type casting only changes the type of
the reference, but it does not create a new object. Type conversion
does create a new object.
DirectCast is faster at runtime than CType.

Under which circumstances? I read this also before but I could not
reproduce it. The speed was equal.

Regards - OHM# (e-mail address removed)
 
Everytime you post, I realise how little I know.

Regards - OHM#

Ken,
Personally that is the key word "error prone"! .NET goes out of its
way to avoid such error prone code!

Luckily VB6 & VB.NET have type safety! I consider this a major
benefit not a drawback!

Note a VB6 Type is a VB.NET Structure, however I would recommend
using a Class instead.

I would "serialize" the structure to a MemoryStream using a
BinaryWriter. I would then calculate the checksum on the
MemoryStream. Both MemoryStream & BinaryWriter are in the System.IO
namespace. Alternatively you can use System.GitConverter.GetBytes to
get byte arrays for individual members however the BinaryWriter &
MemoryStream makes this significantly easier!

I would use an BinaryReader to read the header information
interpreting & "deserializing" as I go. BinaryReader is also in the
System.IO namespace.

By "serialize" and "deserialize" I mean I would implement custom
routines that would convert an object to & from a binary format using
the BinaryReader & BinaryWriter classes similar to what is described
in the following article:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp09182003.asp

Note the samples are C#, with your C++ background you should be able
to convert them.

An alternative to the BinaryReader & BinaryWriter is the
System.Runtime.InteropSerivces.Marshal class. Check out the
StructureToPtr & PtrToStructure methods along with the Copy or Read
methods. Although the method is StructureToPtr you can use them with
either a VB.NET Class or a Structure...

Hope this helps
Jay

Regards - OHM# (e-mail address removed)
 
Sorry, but when you assigned it 17i you already cast it. So the types are
the same by the time it gets to direct cast.

However, I am a little confused over this, because after casting occurs 'o'
still maintains the Type 'Object' in the Locals window although the Object
pointed to is of Type Integer.

Can you adequately explain this to me ?

Regards - OHM#


Armin said:
"One Handed Man [ OHM# ]"
But its primary Type is still Object

Type of what? After DirectCast it is Integer.

Regards - OHM# (e-mail address removed)
 
Doh!
System.GitConverter.GetBytes to get byte arrays for individual members
That should be System.BitConverter.GetBytes.

I'm not sure what a GitConverter does, but I'm sure it involves Gits. ;-)

Jay
 
"One Handed Man [ OHM# ]"
Sorry, but when you assigned it 17i you already cast it.

No, it is only boxed.
So the types
are the same by the time it gets to direct cast.

The type of the reference using o is 'Object'. After DirectCast the type of
the reference is Integer.

If your statement were true both of the following statements would work.
Only the first does:
msgbox(directcast(o, integer).maxvalue)
msgbox(o.maxvalue)
However, I am a little confused over this, because after casting
occurs 'o' still maintains the Type 'Object' in the Locals window
although the Object pointed to is of Type Integer.

Can you adequately explain this to me ?

The IDE shows the *declared* type of o, and this is Object. In the value
column, the *instance* type is shown.
 
What do you mean by boxed ?



Armin said:
"One Handed Man [ OHM# ]"
Sorry, but when you assigned it 17i you already cast it.

No, it is only boxed.
So the types
are the same by the time it gets to direct cast.

The type of the reference using o is 'Object'. After DirectCast the
type of the reference is Integer.

If your statement were true both of the following statements would
work. Only the first does:
msgbox(directcast(o, integer).maxvalue)
msgbox(o.maxvalue)
However, I am a little confused over this, because after casting
occurs 'o' still maintains the Type 'Object' in the Locals window
although the Object pointed to is of Type Integer.

Can you adequately explain this to me ?

The IDE shows the *declared* type of o, and this is Object. In the
value column, the *instance* type is shown.

Regards - OHM# (e-mail address removed)
 
"One Handed Man [ OHM# ]"
What do you mean by boxed ?

A variable declared As Object occupies 4 bytes. If you assign a value type
to the variable, the size of the object can not always be 4 bytes to fit
into the variable. Consequently the object is stored on the heap and the
reference to the object is stored in the variable. Just like reference
types.


Look for "boxed" in
http://msdn.microsoft.com/library/en-us/cpguide/html/cpconvaluetypes.asp

See also KB article 311327:
http://support.microsoft.com/default.aspx?scid=kb;[LN];311327

and (look for "boxing"):
http://msdn.microsoft.com/library/en-us/dv_vstechart/html/vbtchmicrosoftvisualbasicnetinternals.asp




Strange, I didn't find anything in the VB.Net docs.... :-(
 
Jay B. Harlow said:
I'm not sure what a GitConverter does, but I'm sure it involves Gits. ;-)

Jay

Good movie :-)

Anyway, I agree completely about the Type safety thing. C++ allows far too
many nasty bugs and convoluted code due to treating memory as some arbitrary
blob of bits that can be read/manipulated any way you like.
However, the one upside to the C++ behavior is that you don't need a COPY of
the bits if you want to look at it differently. If you want to play
semi-nice and keep the copying to a minimum, you could pin the object, then
use the Marshal class to peek 1 byte (or 1 int, or 1 long, etc.) at a time
and calculate the checksum that way.

Getting back to the original post:

C# does indeed have pointers (check "unsafe" code), and VB can operate
similarly by using the Marshal class and pinned GC handles. However, both
languages are completely type-safe, so you cannot cast arbitrarily (which
really has more to do with the instance data itself rather than the pointer
that is pointing to it).

In a type-safe OO system, you treat entities differently by using
polymorphism - which doesn't do EXACTLY the same thing under the hood, but
allows you to manipulate different entities with like interfaces in a
completely structured and type-safe manner.

If you pin the structure, you can read the memory as if it were bytes with
the Marshal class.

You can always use the binary serializer to serialize the entity to a byte
stream (and deserialize the byte stream back into the entity). Extremely
convenient, but it does add type information to the stream.

-Rob Teixeira [MVP]
 
I understood that primitives are wrapped in a class, but I thought that this
was how they are allways used. Its unclear to me what situations a value
type is stored wrapped and when not.

The texts you recommended I read tell the developer to not "OverBox", but no
example did I see to clarify when this might occur.

Can you illuminate please ? - Thanks for your patience and help here. I had
thought I was clear on this but I am not.

Regards - OHM


Armin said:
"One Handed Man [ OHM# ]"
What do you mean by boxed ?

A variable declared As Object occupies 4 bytes. If you assign a value
type to the variable, the size of the object can not always be 4
bytes to fit into the variable. Consequently the object is stored on
the heap and the reference to the object is stored in the variable.
Just like reference types.


Look for "boxed" in
http://msdn.microsoft.com/library/en-us/cpguide/html/cpconvaluetypes.asp

See also KB article 311327:
http://support.microsoft.com/default.aspx?scid=kb;[LN];311327

and (look for "boxing"):
http://msdn.microsoft.com/library/en-us/dv_vstechart/html/vbtchmicrosoftvisualbasicnetinternals.asp




Strange, I didn't find anything in the VB.Net docs.... :-(

Regards - OHM# (e-mail address removed)
 
"One Handed Man [ OHM# ]"
I understood that primitives are wrapped in a class, but I thought
that this was how they are allways used.

How do you mean this? (if my explanation below is unclear)
Its unclear to me what
situations a value type is stored wrapped and when not.

The texts you recommended I read tell the developer to not "OverBox",
but no example did I see to clarify when this might occur.

Can you illuminate please ? - Thanks for your patience and help here.
I had thought I was clear on this but I am not.

The object is boxed whenever the object is assigned to a variable that also
accepts reference types. The only type (I know of) that fulfills this
precondition is System.Object.
 
After these statement(s)

Dim o As Object
Dim i As Integer = 8
Dim ub as Integer

Then the following statments

o = 8

or

o = i

Result in a New 'Boxed' primitive on the heap with the value which was
assigned.

And 'Unboxing ' is the defererencing of 'o'

ub = o


Do I have this correct now ?

Regards - OHM





Armin said:
"One Handed Man [ OHM# ]"
I understood that primitives are wrapped in a class, but I thought
that this was how they are allways used.

How do you mean this? (if my explanation below is unclear)
Its unclear to me what
situations a value type is stored wrapped and when not.

The texts you recommended I read tell the developer to not "OverBox",
but no example did I see to clarify when this might occur.

Can you illuminate please ? - Thanks for your patience and help here.
I had thought I was clear on this but I am not.

The object is boxed whenever the object is assigned to a variable
that also accepts reference types. The only type (I know of) that
fulfills this precondition is System.Object.

Regards - OHM# (e-mail address removed)
 
"One Handed Man [ OHM# ]"
After these statement(s)

Dim o As Object
Dim i As Integer = 8
Dim ub as Integer

Then the following statments

o = 8

or

o = i

Result in a New 'Boxed' primitive on the heap with the value which
was assigned.
Right

And 'Unboxing ' is the defererencing of 'o'

ub = o

ub = directcast(o, integer)

Right, the integer value on the heap is copied to ub (and ub is on
the stack).
 
OK, So now we have established that. I then put it to you that my original
statement is correct, which is that directCast only works with reference
types, because when they are Boxed, they become referenced. Your assertion
was that Boxed types also work, this is true.

BTW the assignment

Works during compile and runtime. The casting is done implicitly it seems.

Thank you for your patience. I wont bother you further on this one as we
have done it to death.


Regards - OHM






In Holland and Dutch speaking Belgium they say

Heap Heap Hoera,

:-))

Cor

Regards - OHM# (e-mail address removed)
 
Back
Top