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
Quote:
Also, how would one reference a namespace within a particular scope?


To my knowledge, you don't. [edit: The chapter on Namespaces should provide info though if you're curious. My reading of it is that you don't though...] You can do aliasing within certain scopes (to help with conflicts), but that's probably not what you're asking. Full names will work everywhere.

The using block that wants a variable is covered at least a little in this week's tidbit on Statements. It's used as shorthand for a common resource acquisition pattern. (and will be discussed later).

Quote:
What happens if you decide later to change the Area type to float? Any code using the Area expecting an int will choke, right?


Yup, as your tests showed.

Quote:
I sorta get that (unified type system)... an array of objects that offer a string representation or somethin?

What other methods could be used to solve this issue? If this falls under polymorphism, or any other question we're not suppose to ask about yet, then just toss a hint and I'll save this question for later. :)


One of the virtual methods in Object is ToString() which Console.WriteLine uses. Since everything is an Object changing the type doesn't bother anything.

[Opinion]
There are perhaps a few other ways to solve the issue, but they're perhaps best left for later.

I understand that the possibility of the answers to these questions have been posted, I wanted to see how far off base I was, if I am.

1. What is component-oriented programming?

Component-oriented programing is a newer programing para dime that focuses on building reusable, stable, segments of code that can be used in a number of ways by different programs and programmers. Essentially it encourages programmers to build a standardized building block for other programmers to use in a simialer situation.

2. What are the keys to software components in C#?

"properties, methods, and events; they have attributes that provide declarative information about the component; and they incorporate their own documentation" Basically the keys are that the components are completely encapsulated. The code should be self explanatory and should not rely on outside resources. It is plug and play programming.

3. What is Garbage Collection?

The automatic regaining of memory not being used by an unused object.

4. What is exception Handling?

Provides structured and extensible approach to error detection and handling. A more robust net to catch errors and a finer way of handling the situation when one gets through.

5. What benefits do type safety provide you in C#?

It makes it impossible to have uninitialized variables, to index arrays beyond their bounds, or to preform unchecked type casts.

6. What is a unified type system?

A group of types that inherit from the same root (ex. int inherits from the same root object type as double)

7. What are the benefits of a unified type system?

Sharing a common set of operations allowing values of any type to be stored, transported, and operated on in a consistent manner. Also, it supports user-defined reference and value types, allowing for dynamic allocations of objects and in-line storage of lightweight structures.

8. What's the purpose of namespaces?

A namespace is a high tier organizational function in C#. Namespaces contain types and other namespaces for the sake of organizing similar types and namespaces.

9. What directive allows unqualified use of the members of a namespace?

The using directive.

10. What is the entry point of a C# Console application?

A static method named Main, conventionally, serves as the entry point for C# Console application.

11. What's the name of the C# Runtime libraries?

The .Net Framework is the C# runtime libraries.

12. What are the key organizational concepts in C#?

Programs, namespaces, types, members and assemblies

13. What two things do C# assemblies contain and what form are they in?

they contain either applications or libraries, in .exe or .dll forms.

14. What happens to the IL instructions just before the code is executed?

It is automatically converted to processor specific code by the JIT compiler of the .NET Common Language Runtime

15. When are forward decelerations needed in C#?

Forward decelerations are never needed because declaration order is not needed. Only in a few rare cases is forward declarations needed in C#

16. What are the two kinds of variable types in C# what's the difference?

value types and reference types

17. How are C#'s value types subdivided?

simple types, enum types, and struct types

18. How are C#'s reference types subdivided?

class, array, delegate, and interface types.
Thank you for letting me waste your time. -OA
Advertisement
I'm sorry I will be more technical from this post. More specifically, I will speak about OO design. And to warn you about what you're going to read: it's a very long question, without much question mark. I must confess that I still think about that issue (although I'm not sure I should call this an issue) and not everything is clear in my mind.



I discovered interfaces a few days ago (when I was writing my new XNA post on my blog), and - maybe I'm wrong - but they are something quite interesting from a OO design point of view. Let me explain that.

When you inherit from a class, you bring that class behavior in your new child class, making this child class a subtype of the parent type. OOD-wise, subtypes are quite restricted when it comes to the redefinition of their behavior - The Liskov Substitution Principle tells us that the subtype should behave like it's ancester type from the point of view of the client (there are very good reasons for that). That's something which is pretty hard to enforce, especially if you allow someone to inherit classes from your library, but it has to be enforced because when you create a class that has to be inherited, you make a number of assumptions about how it's going to be used. To sum up this: when you inherit a class, you must complie not only to the class contract (the virtual methods declarations) but also to an implicit behavior contract.

Interfaces are not subject to the same limitations - or, ot be more exact, they are less subject to these limitations. An interface brings no behavior with it, and that gives you additional freedom when you inherit it because you're not creating a subtype of the interface - you're implementing the interface, and that's quite different.

Of course, you still have to comply to the interface definition - but you're free to do whatever you want to support it. A class that inherit the IDisposable interface must implement the Dispose() method, but it can do it in whatever way it wants, as long as it complies to the interface contract. The big point here is that you don't have to implement a particular behavior.

Now, I may be wrong - there are good OO guys out there that might not share this pieve of opinion. I'm not even sure that the discussion should go here (in which case Jeromy will PM me, and I will remove that post and post it in the SE forum as a thread). However, since we are speaking of that interface keyword, I though that some of its implications on OOD would be a good addition to this thread (and to this workshop). To be honnest, I find C# interesting for the new possibilities it offers to me - as a programming language. All those delegates, sealed classes, interfaces, properties or indexers are quite cool. But I still have to study them [smile].



And as you see, there is no question mark. But that's still an open question-like post. Or if you prefer: please, can you comment on this? (yes! question mark zomg!)
After reading the first chapter, I have some questions. I will start with a piece of code:

Simple hello world program.
using System;class Hello{    static void Main() {        Console.WriteLine("Hello world!");    }}


I understand that this creates a class called Hello with a static void function called Main. However:

Does Main have some special meaning like the int main() function in C++?

How can the application write "Hello world!" if the Main() function isn't invoked somewhere in the program? I would make an instance of the Hello class and invoke the Main function like this:

using System;class Hello{    static void Main() {        Console.WriteLine("Hello world!");    }}Hello hello = new Hello();hello.Main();


Other questions:
What is the difference between int,int[,] and int[][]?

In the section 1.6.4 Fields, what is the type 'byte' used for the variables r,g,b?

I don't really understand the difference between 'ref' and 'out'. They were described to do exactly the same thing.

What does the 'get' statement do in the following method for example? Shouldn't return be enough?
public int Count {
get { return count; }
}

And why does the Count function start with the keyword public when they get public by default?
Quote: Original post by password
After reading the first chapter, I have some questions. I will start with a piece of code:

Simple hello world program.
*** Source Snippet Removed ***

I understand that this creates a class called Hello with a static void function called Main. However:

Does Main have some special meaning like the int main() function in C++?

Yes, Main is recognized as the main entry point of your program.
Quote: Original post by password
What is the difference between int,int[,] and int[][]?

int is a single integer.
int[] is an array of integers.
int[,] is a 2D-array.
int[][] is an array of arrays, and can also be used to represent 2D arrays (it's done this way in other languages such as C++ and java). These are also called jagged arrays.

I think int[][] is a bit faster than int[,], but that could change in the future. I prefer (opinion!!) using int[,] as initializing it is easier:

// Using [,]int[,] matrix1 = new int[3, 3]; // 3x3 matrix in one step// Using [][]int[][] matrix2 = new int[3][]; // I often forget whether it's [3][] or [][3]. Compiler tells me it's [3][]for ( int i = 0; i != 3; ++i )    matrix2 = new int[3];


Array initializers are also different:
int[,] x = new int[,] { { 1, 2, 3 },                        { 4, 5, 6 },                        { 7, 8, 9 } };int[][] y = new int[][] { new int[] { 1, 2, 3 },                          new int[] { 4, 5, 6 },                          new int[] { 7, 8, 9 } };


Another difference which you might encounter often: retrieving the length
int[,] x = ...;int s1 = x.GetLength(0);int s2 = x.GetLength(1);// Valid indices for x : [0..s1, 0..s2]int[][] y = ...;int t1 = x.Length;int t2 = x[0].Length; // Be careful that x[0] != null // Valid indices for x : [0..t1][0..t2]


Jagged arrays (the [][] kind) have one big advantage: the "secundary arrays" need not be the same size.

E.g. [,] arrays always have the shape
// Possible with both [,] and [][]xxxxxxxxxxxxxxxxxx

Each row having the same number of items. Jagged arrays let you have more freedom in this regard:
// Possible only with [][]xxxxxxxxxxxx

which you can create with
int arr[][] = new int[5][];for ( int i = 0; i != arr.Length; ++i )  arr = new int[1 + i];
Advertisement
Quote: Original post by password
After reading the first chapter, I have some questions. I will start with a piece of code:

1- I'll leave someone knowledgeable to answer that for you.

2 - ....
Quote: Other questions:
What is the difference between int,int[,] and int[][]?

int is just a regular integer.
int[] is an array of integers.
int[,] is a two-dimensional array. The columns and rows must always be the constant. For example, int[,] example1= new int[4,3]; The array will always have 3 columns and 4 rows.
int[][] is a multi-dimensional and can be what's called a jagged array. A jagged array can have rows with different number of columns. For instance,
int[][] example2 = new int[4][]; //notice the empty column bracket.example2[0] = new int[5];example2[1] = new int[3];example2[2] = new int[1];example2[3] = new int[15];

Here's how example1 and example2 look assuming they're initialized with 0s.
example1:          example2:0000               000000000               0000000               00000               000000000000000

Quote: In the section 1.6.4 Fields, what is the type 'byte' used for the variables r,g,b?

Byte is just another Data Type. It's actually an 8 bit unsigned integer with a range of 0 - 255.

Quote: I don't really understand the difference between 'ref' and 'out'. They were described to do exactly the same thing.

In short, you'd use a ref when you care about the value going into a function as well as the value coming out. That variable must be initialized with a value however.

You'd use an out when the only thing you care is the value coming out of the function. The variable doesn't have to be initialized.

An example:
public void whatDoIDo(ref int foo, ref int bar){    foo = 5;    foo = foo * 2;    bar = 10;    bar = bar * 2;}public void nowWhatDoIDo(out int foo, out int bar){    foo = 5;    foo = foo * 2;    bar = 10;    bar = bar * 2;}

If you tried this:
int x, y;whatDoIDo(x, y); // the compiler is going to scream at you                 // because you didn't initialize x and ynowWhatDoIDo(x, y); // the compiler gives the green light                    // x and y go in uninitialized but                    // but come out as x = 10 and y = 20


Quote: What does the 'get' statement do in the following method for example? Shouldn't return be enough?
public int Count {    get { return count; }}


And why does the Count function start with the keyword public when they get public by default?


That method is a special called a Property. It takes a private field of a class and allows other methods and classes to access it. Every Property method has a get and set method. So in that example the get method simply returns the value of the private field count. It's public so other methods can access the Property and by the extension the value of the private field count.

Beginner in Game Development?  Read here. And read here.

 

Quote: Original post by Alpha_ProgDes
Quote: What does the 'get' statement do in the following method for example? Shouldn't return be enough?
public int Count {    get { return count; }}


And why does the Count function start with the keyword public when they get public by default?


That method is a special called a Property. It takes a private field of a class and allows other methods and classes to access it. Every Property method has a get and set method. So in that example the get method simply returns the value of the private field count. It's public so other methods can access the Property and by the extension the value of the private field count.


Could I just make a minor correction to be a bit clearer? Not every property has to have a get and a set method, you can have properties like the one in the example with only a get method, which effectively makes it read only. As you might suspect, you can also have a property with only a set method, which makes the property write only. And of course finally you can have a property with both get and set for read/write access. Here is an example of the Count property expanded with a 'set' method

public int Count {    get { return count; }    set { count = value; }}

Quote: Original post by Emmanuel Deloget
interfaces

Some people agree, some people don't. I don't know which side I'm on personally as I'm still trying to find out how to best use them. Sometimes I have the impression inheritance as we know it should be thrown away as it combines two things which should better be separated: it defines subtype-relationships, and offers some kind of efficient composition. My idea is to only be able to use objects through interfaces, and let only interfaces define subtype relationships.

Anyway, regarding contracts of interfaces, a while ago I had a discussion with my professor regarding this issue. He claimed that it was very much necessary to provide interfaces with contracts, while my idea was that none should be given. Instead, the entities using the interfaces would have to indicate how they are being used. For example, if I have a map-function which applies some function to every item in an array:

interface IFunction<T>{    T Apply(T t);}void Map<T>(T[] array, IFunction<T> func){    for ( int i = 0; i != array.Length; ++i )    {        array = func.Apply( func );    }}

Theoretically, the C# interfaces have contracts, but it's implicit, hidden in the type system: it establishes that IFunction<T> objects have a method Apply taking one T-argument and returning a T-value. But adding any more information to it would just limit Map's possible uses. So, IFunction should make no (extra) guarantees, and Map should specify in its contracts that it will call Apply on each item in the array, in order, and store the results in-place.

However, there are cases where it's more intuitive for interfaces to actually have contracts. Consider different searches: breadth-first, depth-first and dijkstra. They're basically the same algorithm, but internally use a different data structure: depth first uses a stack, breadth first a queue, dijkstra a priority queue.
interface ISearchContainer{    void   Push(State s);    State  Pop();    bool   IsEmpty { get; }}Solution GeneralSearch(ISearchContainer container, State initState){    ...}Solution DepthFirstSearch(State initState){    return GeneralSearch( new Stack(), initState);}Solution BreadthFirstSearch(State initState){    return GeneralSearch( new Queue(), initState );}// ...

Does ISearchContainer need a contract? My professor says yes, because the GeneralSearch algorithm clearly depends on it. I say no, because in order to allow any kind of search, you'll have to be extremely vague anyway about how items are Pushed and Poped. It would be better for GeneralSearch to specify how it will be using the container it receives. From the outside, you still have your full specification and everything is guaranteed to work as established in the contracts: if you want a depth-first search, you'll pass a Stack (which has a complete specification) to GeneralSearch (which indicates clearly how it will use this stack), and voilà, you have your working depth first search.

The problem is of course that GeneralSearch will probably have a pretty complex contract. But at least, it will be fully specified. This would not be the case with vague contracts as my professor would want them.

Anyway, I'm not sure who of us is right. I guess Liskov's substitution principle would be thrown out the window using my way. Maybe not a bad thing :) I'll have to bring up the subject again someday.
Quote: Original post by SamLowry
int is a single integer.
int[] is an array of integers.
int[,] is a 2D-array.
int[][] is an array of arrays, and can also be used to represent 2D arrays (it's done this way in other languages such as C++ and java). These are also called jagged arrays.

I think int[][] is a bit faster than int[,], but that could change in the future. I prefer (opinion!!) using int[,] as initializing it is easier:


Then i'll use the method that creates an array containing arrays, since it's faster and can contain any array regardless of size.


Quote: Original post by Alpha_ProgDes
If you tried this:



int x, y;

whatDoIDo(x, y); // the compiler is going to scream at you

// because you didn't initialize x and y



nowWhatDoIDo(x, y); // the compiler gives the green light

// x and y go in uninitialized but

// but come out as x = 10 and y = 20


In that case, always using the out keyword should be better, since it is just like a reference except that it also can handle unitialized variables. It's like a better version of ref, or i'm I misunderstanding?

This topic is closed to new replies.

Advertisement