Wednesday, March 10, 2010

Arrays (C#, .NET, Visual Studio 2008)


In previous DevCasts, we accessed command-line parameters by way of the parameter array. We saw that arrays are declared using square brackets ("[]"), that every array-type has a "length" parameter, and that we could access elements of an array using a numerical "index". This DevCast will give details about different types of arrays and how they can be used in C#.

The solution for this DevCast consists of a single project and code-file--all named "arrays". From now on, I will not describe every aspect of the code but hope you will be able to follow from what you see. If you don't understand the line "using System;", class declarations, or the importance of the "Main" method, please watch one of the previous DevCasts.

The first type of array we will look at is called a "single-dimensional array". The parameter array created through command-line arguments is of this type. To declare a single-dimensional array for our own use, we first must declare the type of each element, then give it a name (in this case, "numbers"), and then assign it an instance of a new array object of the same type with a predefined length.

You can think of a single-dimensional array as a single list of objects. We set the "numbers" array to be length 5 and we can test this by getting the "Length" property and writing it to the console. The length of 'numbers' is 5 just as we declared it and expected it to be.

The next type of array to look at is what's called a "multidimensional array". We're going to make a 2-dimensional array because that is the simplest to visualize and to work with but there's no limit to the number of dimensions. To create the 2-dimensional array we start off with the element type, as always, but in the square brackets, we insert a comma to indicate that one index will be on the left, and another index will be on the right. This makes more sense when assigning the new array object. First, we'll give it the name "names" and assign it a new string array with the size of one dimension 5 and the size of the other dimension 4.

You can visualize this as a table containing 5 rows and 4 columns. Or maybe, you would prefer 5 columns and 4 rows. Let's find out how the computer thinks about this by printing the "Length" of this array to the console.

The computer says the length of the "names" array is 20 elements long. Basically, this means the computer is placing each dimension end-to-end to create a long list and calculating the position of any one element given the indices we provide. It's best that we continue to think of it as a table because of this.

The final type of array is called a "jagged array" or, more technically, an "array-of-arrays". The multidimensional array we saw before is such that every row of elements has the same number of columns. In the jagged array, each row can be of a different length. This is because the jagged array is created by declaring an array where each element is also an array.

Declaring the jagged array may look different from the single-dimensional array, but, in fact, they are extremely similar. To illustrate the similarity, let's start off by making a single-dimensional array of bytes. We'll make it 5 bytes long just like the "numbers" array we made earlier and we'll give it the name "scores". We can think of this byte array as a single data-type just like "int" or "string" so, if we want to make an array of byte arrays, we just add the square brackets to the end of this type. Notice the empty brackets at the end of this line. We do that because we don't know the size of each internal array.

To prove that "scores" is a simple single-dimensional array, let's print the length to the console. This tells us that scores contains 5 elements. The only difference between "scores" and "numbers" is each element of "scores" is an array-type whereas each element of "numbers" is an integer-type.

The internal arrays of "scores" do need sizes before we can work with them, so let's do it programmatically with a for-loop. We want to populate every element of "scores" so we start the loop at "0" and continue until "scores.Length". The definition of "scores" says that each element must be a byte-array so we say "scores[i] = new byte[i+3];" Notice, this will force each internal array to be a different size.

Remember that we access an element of an array by putting the position of that element in square brackets after the array's name. Since each element of the "scores" array is also an array, we can discover its length with the "Length" property. Looping over the scores array will give us access to each internal array and we can print its length with "scores[i].Length".

Run this one more time in the debugger to see that we can access every array we have created.

I'm Justin Mancinelli; thanks for watching.



Links:
http://msdn.microsoft.com/en-au/library/hh0eh6yz.aspx
http://zpjdevcast.blogspot.com/

Thursday, February 25, 2010

Command Line Parameters (C#, .NET, Visual Studio 2008)


In the previous "Hello World" DevCast, we created a program which was able to process arguments from the command-line. This time, we will review how that was done and discover another method to access the array of command-line parameters.

I have created a solution called "CommandLine" and two projects: one, called "CmdLine1"; and the other, named "CmdLine2".

For "CmdLine1", we will write something very similar to the "HelloWorld3" project from last time. We start by declaring that we will use the system namespace, create a class which will be called "CommandLine", and add the required entry method which, as we learned from "Hello World", must be declared with the keyword "static" and be called "Main" with a capital "M".

The "Main" method is the first method called when our program is started and that becomes obvious when we see how to access command-line arguments. Looking back at "HelloWorld3", you see that we type the program's name and then any parameters we want to send to the program. When we push enter, the console puts all of the parameters into an array and then executes the program by calling the "Main" method, using that parameter array as an an argument of the method.

We access the parameter array by defining the "Main" method such that it will accept an array argument. C# is a stongly typed language so each variable must be declared along with an associated type. In the case of the parameter array, we need to declare the variable "args" to be an array-type containing string-type elements. Square braces imediately after a type declaration tell the compiler that this will be an array containing elements of only that type.

If you have watched the "HelloWorld" DevCast, you will already be familiar with how we access the elements of the "args" array and properties of the array itself. I will paste in some code very similar to that example. One thing to note is that Length is a read-only property of the "args" array. You can see that in the tool-tip where it only mentions that it "gets" a 32-bit integer value. If we could modify the value, the tool-tip would mention that we could also "set" the value. Since "Length" cannot be set by the programmer, it means we cannot change the size of the array after it has been created.

The biggest difference between this example and the previous "HelloWorld3", is the string formatting with multiple arguments. The "zero in curly braces" will be replaced by the value of the argument "i" and the "one in curly braces" will be replaced by the value of the argument "args[i]", or, in other words, the element of the "args" array at position "i".

For the second project, I'll copy the first code-file because the only big difference is going to be how we loop through the "args" array. Change the class name to "CommandLine2" and then take a look at the "for-loop".

A "for-loop" is generally used when you know where you want to start and where you want to end. In this example, we want to start at the first element of the array and continue until the last element of the array. Arrays begin at index 0 and end at their length minus 1 so we start the "for-loop" counter at 0 and add one until until the counter counter is equal to the length of the array.

Since looping over an entire array is so common in programming, C# has a "foreach" loop to make things easier. Simply tell it to put each element in the array into a variable of the same type. Each element in the "args" array is of the string type so we write "foreach(string s in args)" where "s" can be any name that hasn't been used yet.

Now, each element of the "args" array will be sequentially put into "s" so we can write each of them to the console with "Console.WriteLine(s)".

When we execute this program from the console, you can see it runs with the same result as the previous "HelloWorld3" example.

I'm Justin Mancinelli, thanks for watching.



Links:
http://msdn.microsoft.com/en-au/library/cs8hbt1w.aspx
http://zpjdevcast.blogspot.com/

Saturday, February 20, 2010

HelloWorld (C#, .NET, Visual Studio 2008)


When programmers dive into a new language, the most common first program to write is the "Hello World" program.

In this episode, we will be writing four such programs to get an idea of the different ways to use C# to create essentially the same, if not exactly the same, result.

Since the "Hello World" program is usually the first step in learning a new language, I will assume we are new to the Visual Studio environment as well. So let's start with creating a new project.

Visual studio comes with many project templates and they are very helpful when you are creating more complex programs but for all our "Hello World" programs, we will start with an empty project. This creates a "Solution" folder which contains a "Project" folder, and, in that, a "References" folder.

A solution can hold many projects so lets rename the solution to "HelloWorld" and rename "Project1" to "HelloWorld1". I said we are going to write four "Hello World" programs so let's make the next three now. If you click on "New Project" in the "File" menu, you'll notice a warning telling us we must "either save or discard changes in the current project before creating a new project." That's because it's actually talking about the "Solution". We cancel that action and, instead, right-click on the solution name and choose "Add->New Project...". It says we must save the current project in order to do so but it's still talking about the solution, not the project. Now we can add the projects, HelloWorld2, 3, and 4 to the solutions folder.

All of these projects will be console applications and by going into the project properties, you can see that is the default "Output type". So we don't need to change anything there and we are ready to write the programs.

Right-click on the project "HelloWorld1" and select "Add->New Item...". Again, we see several code templates to help us design new software but we will choose "Code File" which will give us "A blank C# code file". Let's simply name it "Hello1.cs". We choose the extension "cs" because it is a C-Sharp program.

When we push "Add", it is added to the "HelloWorld1" project folder and automatically opened for editing.

First, we will make a class called "Hello1" and mark it as public so that it can be referenced from anywhere in the program. This is not strictly necessary since this program will only consist of one class but it is important to know how to use in larger programs.

Next, we create a method within the class called "Main". This has been underlined red because every method must have a return type and we indicate that this method will not return a value with the "void" keyword. C# is case sensitive so it is important to name this method with a capital "M". The reason, is that the compiler will look for this method specifically as the first method to run when the application is executed. However, just naming it this way isn't enough. We also need to declare the method as "static" so that it will have the same reference no matter how many instances of the containing class are created. If the "Main" method is not declared "static" then every instance of the class "Hello1" will have its own "Main" method. We'll also declare it as "public" since a larger program may want to reference it from outside the "Hello1" class.

So, we have the "Hello1" class to hold the "Main" method which will be run on execution but right now it's not doing anything. This is supposed to be a "Hello World" program, so let's make it write "Hello, World!" to the console. This is very easy using the .NET Framework Class Library. Just write "System.Console.WriteLine("Hello, World!");". There's a class "Console" in the "System" namespace with a method "WriteLine" that takes a string argument. Notice, we didn't have to create a new instance of the Console object. That's because "WriteLine" is declared "static" just like our "Main" method.

If we try to run this in the debugger, we get an error and that's because it's trying to compile all of the projects which don't have any code files. So, let's just copy "Hello1.cs" to all the other projects for now. Try debugging again and the console window appears just long enough to write "Hello, World!" to a line. It disappears because there's nothing in our program to make it wait. After writing the line, there's nothing left to do so the program simply terminates. We can see it on the screen longer by choosing "Start Without Debugging" from the "Debug" menu. The line "Press any key to continue..." is added by the debugger.

For the second program, we will simply rename "Hello1.cs" to "Hello2.cs".

In "Hello1.cs" we wrote this long line to access the "WriteLine" method. I mentioned that the "Console" class was in the "System" namespace. A single namespace could hold hundreds of class definitions and, if we want to use lots of them, it would be annoying to continue writing such long lines of code. Fortunately, we can simply tell the compiler, from the start, that we're going to be using the "System" namespace. To do that, we just write the line "using System;" at the top of the file and now we can reference the "Console" class directly. That saves a lot of time. We can run this in the debugger but we have to set this as the startup project first or else "Project1" will open in the debugger instead.

For "Hello3.cs" we will see how to access command-line arguments from the program. First we'll indicate that we want to use the "System" namespace as in "Hello2.cs" but now we'll change the "Main" method to accept arguments by telling it to store them in an array of strings called "args". We can access the argument array later to do any number of things. For this program, we will simply tell the user how many arguments they provided and then write them back to the console.

We now have a variable of type array called "args" and we can find the length of it by calling "args.Length". The "Length" property is defined for every array instance. We can write its value to the console in a friendly manner using string formatting. The world of programming likes to start counting at zero so to reference the first value, we write "{0}".

Next, we want to display each value in the "args" array. A very useful code pattern is the "for loop". We create a temporary integer variable "i" starting at "0" and tell it to keep adding "1" as long as "i" is less than the length of the array. Before it adds "1", however, we tell it to write a line to the console containing the value of the array at that index.

I haven't found a way to debug with input arguments so we need to find our program in the console to try it out. Notice that it will take any number of arguments including characters, numbers, and symbols.

Lastly, we have "Hello4.cs". This will just show how to return other types rather than "void". Remember, every method must indicate a return type. Previously, we were returning void and that's all well and good for such a simple program but you may want to return different values depending on the success of the program. Change "void" to "int" to indicate we will return an integer value. If we try to build the program now, we get an error because we're not returning anything. Before we had "void" so it was expected that we wouldn't return anything but now the method is expected to return an integer. We can do that with "return 0". It's common practice to use a value of "0" to indicate everything's normal. Positive numbers generally indicate the method was successful but something changed while negative numbers mean something went wrong.

I'm Justin Mancinelli.
Thanks for watching.



Links:
http://msdn.microsoft.com/en-au/library/9ys06tc9.aspx
http://zpjdevcast.blogspot.com/