Advertisement

C# Workshop - Week 1 (Ch. 1 & 2) - Advanced

Started by July 01, 2007 12:15 AM
337 comments, last by paulecoyote 17 years, 2 months ago
I am sorry, I know this has been covered in an earlier post, but I don't have time to dig through that many posts, I still have quite a bit of reading to do. So onto the question.

If an Object is the instance of a class, then in boxing and unboxing is

using System;
class Test
{
static void Main() {
int i = 123;
object o = i; // Boxing
int j = (int)o; // Unboxing
}
}

turning int i into an instance of a class? And then, is int j the returning of, the now object (an instance of a class) back into its original value type int?
Thank you for letting me waste your time. -OA
Quote: Original post by Strewth
Quote: Original post by Exershio
hey. I know when you create programs in VC++, the person using it must have the VC runtime installed on their computer. Is this the same case with C#? or do they just need the .NET framework and only that?


An appropriate version of the .NET Framework is all that is required. It is backwards compatible, so (in most circumstances) a .NET 1.1 application will run on a machine with .NET 2.0 or .NET 3.0 installed.


That's not quite correct. The API is backwards compatible, although some part of it is deprecated (you can compile .NET 1.1 code with .NET 2.0 tools), but not binaries. If you want to run compiled .NET 1.1 application you need .NET 1.1 Framework, for .NET 2.0 app you need .NET 2.0 Framework and so on.
Advertisement
Quote: Original post by popcorn
Ok but how would you get access to the actual runtime type methods so that you could use UseWand() etc but still treat it as a characterClass.


Ok someone with more experience in c# will need to check this. But you can't(atleast in C++). To call UseWand() you have need a reference to a Healer class. This is done via casting.
CharacterClass myClass = GetPlayerClass();Healer healerClass = (Healer)myClass;  //Cast CharacterClass to Healer classhealerClass.UseWand();


The above code does what you want but is not safe, because if myClass isn't a healer class this would cause an exception. If for example GetPlayerClass returns a Tank Class, it doesn't have a UseWand() function.
If you wanted to do the above safely then you would have to check the type first using Runtime Type Info (RTTI). But this is getting a little advanced (lookup typeOf and GetType function if you wanna find out more).

The point of using virtual functions is that you use the same name to call different functions. In the example given earlier when you call Attack() the application calls either Healer.Attack, Nuker.Attack or Tank.Attack depending on the object that myClass refers to.
Healer.Attack then calls UseWand().

This is kinda getting advanced an will probably be explained alot better when we actually get to chapter 10 an talk about classes an inheritance.

HTH
How does memory in C#, specifically the stack and the heap(free store) work? Is it the same as in C++ where the new keyword throws it on the heap and returns a pointer? Well, I guess in the case of C# the pointer is called a reference, correct?

Anyhow, was trying to answer this question:

57. What's the main difference between classes and structs?

I got a little bit confused because of what I read in the text which states:

"Like classes, structs are data structures that can contain data members and function members, but unlike classes, structs are value types and do not require heap allocation. A variable of a struct type directly stores the data of the struct, whereas a variable of a class type stores a reference to a dynamically allocated object."

Any elaboration on that would be appreciated.

Thanks,

Shawn

public class RefType{    public int x;}public struct ValueType{    public int x;}// ...RefType RefA, RefB;ValueType ValueA, ValueB;RefA = new RefType();RefA.x = 42;RefB = RefA;RefA.x = 196;// note: no new needed.ValueA.x = 42;ValueB = ValueA;ValueA.x = 196;


So, what does x for the four variables equal?
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Answer:
ValueB.x is 42, RefA.x is 196, RefB.x is 196, ValueA.x is 196.
Quote: Original post by shawnre
How does memory in C#, specifically the stack and the heap(free store) work? Is it the same as in C++ where the new keyword throws it on the heap and returns a pointer? Well, I guess in the case of C# the pointer is called a reference, correct?

Anyhow, was trying to answer this question:

57. What's the main difference between classes and structs?

I got a little bit confused because of what I read in the text which states:

"Like classes, structs are data structures that can contain data members and function members, but unlike classes, structs are value types and do not require heap allocation. A variable of a struct type directly stores the data of the struct, whereas a variable of a class type stores a reference to a dynamically allocated object."

Any elaboration on that would be appreciated.

Thanks,

Shawn

As I understand it, there is a strong difference between reference types and value types. An instance of a class is used through a reference (the variable you use is a reference to this class). An instance of a struct is a value - even if it has been "created" using new.

There is a good example of this difference on page 24 of the specs, from line 38 to 48.

Regarding the memory model, this is not described in the specs. My guess is that we should try to not use the same terminology than the one we use in C++ - except maybe for the heap, with the addition that it's garbage collected. The notion of stack is not very pertinent in C++.
Advertisement
Quote: Original post by EternalNewbie
Quote: Original post by popcorn
Ok but how would you get access to the actual runtime type methods so that you could use UseWand() etc but still treat it as a characterClass.


Ok someone with more experience in c# will need to check this. But you can't(atleast in C++). To call UseWand() you have need a reference to a Healer class. This is done via casting.
*** Source Snippet Removed ***

The above code does what you want but is not safe, because if myClass isn't a healer class this would cause an exception. If for example GetPlayerClass returns a Tank Class, it doesn't have a UseWand() function.
If you wanted to do the above safely then you would have to check the type first using Runtime Type Info (RTTI). But this is getting a little advanced (lookup typeOf and GetType function if you wanna find out more).

The point of using virtual functions is that you use the same name to call different functions. In the example given earlier when you call Attack() the application calls either Healer.Attack, Nuker.Attack or Tank.Attack depending on the object that myClass refers to.
Healer.Attack then calls UseWand().

This is kinda getting advanced an will probably be explained alot better when we actually get to chapter 10 an talk about classes an inheritance.

HTH


Actually C# provides you with two handy keywords just for this kind of thing.

"is" and "as".

So to rewrite your code in a way that would make sure it works properly.
CharacterClass myClass = GetPlayerClass();if(myClass is Healer){     Healer healerClass = (Healer)myClass;  //Cast CharacterClass to Healer class     healerClass.UseWand();}


This will make sure your character class is compatible with the cast you are trying to make.

Since I already started it, let me show how the keyword "as" would work here.

CharacterClass myClass = GetPlayerClass();Healer healerClass = myClass as Healer;  if(healerClass != null){     healerClass.UseWand();}


"is" checks to see if the cast is a valid one, while "as" does the cast and returns a null if it is not a valid cast. These are two very powerful keywords that are way under used in C# in my opinion.

Hope that helps.

theTroll

Fixed the typo.. woops.

[Edited by - TheTroll on July 4, 2007 2:36:59 PM]
Oh yeah forget about is (didn't really know about as).

Definatly powerful features and wish they were available in c++. Tho thinking about it I think if you over use them then its probably a sign of bad design.
But when using generics they would be really useful.

But I think thats getting a bit advanced and into design philosophy which is probably best left for when we're further into the workshop.

p.s I assume thats a typo and you meant
Healer healerClass = myClass as Healer;

or am i missing something?
I have been thinking about the "right" way to do what you wanted, and I realized that even "is" and "as" might not be the "best" way.

So I think this is the way to go.

CharacterClass myClass = GetPlayerClass();Type type = myClass.GetType();if(type.GetMethod("UseWand") != null){     healerClass.UseWand();}


This would just test to see if myClass has a GetWand method with no casting required. The advantage with this way, is that you can add more inherited classes that use the GetWand method and not have to worry about changing the core code. To make it even "better", you can make the UseWand an interface, and then use the GetInterface method of Type to make sure that it had that interface before you tried to use it.

Ok, I will shut up now.

theTroll
Quote: Original post by TheTroll
I have been thinking about the "right" way to do what you wanted, and I realized that even "is" and "as" might not be the "best" way.

So I think this is the way to go.

*** Source Snippet Removed ***

This would just test to see if myClass has a GetWand method with no casting required. The advantage with this way, is that you can add more inherited classes that use the GetWand method and not have to worry about changing the core code. To make it even "better", you can make the UseWand an interface, and then use the GetInterface method of Type to make sure that it had that interface before you tried to use it.

Ok, I will shut up now.

theTroll

There's a reason such code is frowned upon. You're bypassing the type system. What's the point of using a statically typed language if you're going to rely on reflection and use types as nothing more than metadata at runtime? You might as well use a dynamically typed language so that you won't have to deal with the formality of writing type annotations everywhere.

I'm not saying is or as or reflection should not be used, but you should know exactly when and why. Your example doesn't strike me as a situation where their use is justified.

This topic is closed to new replies.

Advertisement