Thursday, 4 December 2014

C#.NET Tutorial - Day - 24 - Debugging - The tool windows


THE TOOL WINDOWS



When debugging in Visual Studio or one of the Express versions, the tool windows in the bottom of the screen will change and new windows will be revealed (unless you have turned them off). The windows are called something along the lines of "Locals", "Watch", "Call stack" and "Immediate window" and they are all related to the debugging experience. In this chapter we will look into each of them and show you what they can do for you.


Locals

This window is the most simple of them all. When a breakpoint is hit, all local variables will be listed here, allowing you to get a quick overview of their name, type and value. You can even right-click in the grid and select "Edit value", to give a variable a new value. This allows you to test your code under other conditions than the current ones.


Watch

The Watch window is a bit like the Locals window, only here you get to decide which variables are tracked, local or global. You can add variables to watch over by dragging them from the code window, from the Locals window or by writing its name on the last, empty line. Your variables will stay in the Watch window until you remove it again, but will only be updated when you are debugging within the current scope. For instance, a variable in function A will not be updated when you are stepping through function B. Just like with the Locals window, you can right-click a watched variable and select "Edit value" to change the current value of the variable.


Call Stack

The Call Stack window will show you the current hierarchy of called functions. For instance, if function A calls function B which calls function C which then calls function D, the Call Stack window will show it, and you will be able to jump to each of the function declarations. You can also see which parameters were passed to each function. In the simple examples we have worked with so far, this might seem pointless, since keeping track of which function calls which function is trivial, but as soon as your code reaches a higher level of complexity and you have function in classes calling function in other classes, the Call Stack can be a real life saver.


Immediate window

The Immediate window is probably the most useful of them all. It allows you to execute custom lines of code in the current context of the debugger. This allows you to check variables, alter their values or just simply test a line of code. You simply type it into the window, hit Enter and the line will be executed. Type a variable name, and its value will be printed. Set a variable value by writing a = 5. The result, if any, will be printed and any changes you make, will be reflected when you continue the execution of the code. The Immediate window is like a C# terminal, where you can enter code and see the results immediately - once you get used to it, you might become addicted. I know I am.



Wednesday, 3 December 2014

C#.NET Tutorial - Day - 23 - Debugging - Stepping through the code


STEPPING THROUGH THE CODE



In this post, we will look into stepping through your code, which is another very essential part of debugging. For the purpose, I have written this simple application: 




It simply manipulates the variable "a" a couple of times and the outputs the final result. Try placing a breakpoint, as described in the previous post, on the very first line where a is used (and declared). Now run the application. The execution is stopped and you can hover your mouse over the a, to ensure that what we learned in the previous post is in fact true: The variable only contains the default value, because the code that assigns the value (in this case 5), has not been executed yet, but let's change that. From the Debug menu, select the "Step over" option, or even better, use the keyboard shortcut F10. The execution will now proceed to the next relevant line and if you hover your mouse over the a variable, you will now see that it has a value. Try again, and you will see the value change according to the lines being executed one by one, until you have reached the end. 

Okay, so that was pretty basic, but also very useful, as you will realise once you start writing more complicated code. In this example, the flow of the code was very simple, since we stayed within a single function, but what if your code starts spreading over multiple classes and/or functions? Try this example: 





Place a breakpoint on the first line of the Main method and run the application. Now use the "Step over" function to step through each line. As you will see, it moves over the function call without any notice - that's simply how debugging works. Now, try again, from the start, and once you have stepped to the line with the MakeComplicatedCalculation() call, select Debug -> Step into, or use the keyboard shortcut F11. The debugger now steps into the first possible function call, allowing you to step through that function as well. As you can probably imagine, this allows you to step through a complicated block of code, while only entering the function calls that interests you. 

If you step into a function and then realise that you would rather return to the previous context, you use the very logically named option from the Debug menu called "Step out" (keyboard shortcut is Shift+F11). This will return you to your previous context, which obviously means that you can step into as many function calls as you want to, and then find your way back by using the step out option.

Tuesday, 2 December 2014

C#.NET Tutorial - Day - 22 - Debugging - Breakpoints


BREAKPOINTS



The very first thing about debugging that you need to know, is the breakpoint. It actually does exactly what the name implies - it marks a point in your code where the execution will take a break (and no, it won't actually break your code, don't worry). Placing a breakpoint in Visual Studio or one of the Express versions, is as simple as left-clicking in the gutter, which is the grey are to the left of your code. Once you click it, you will get a shiny, red circle as a reward - this circle marks where the debugger will halt when you execute your application. You better have a look for your self, and to see the effect, we will use the following piece of code: 




Now, can you predict the result just from looking at the code? Probably, and if not, you could just get out the old calculator and do the math, but that's not really the point. Just imagine the amount of code being much bigger, and let's debug the thing! Place a breakpoint by clicking in the left gutter - your IDE should now look something like this: 




Okay, you're ready to start your first debugging session. As soon as you have placed the breakpoint, you can just run your application like you normally would - from the menu, the toolbar or by pressing F5. What happens now is that the application is executed just like normal, but as soon as a line with a breakpoint is reached, the execution is stopped right before that line would be executed. In this case, it means that the variables a, b and c will have a value, but d will only have it's default value (which is 0 for an integer), since it won't be set before the line with the breakpoint has been evaluated. Now, here comes the cool part - try hovering your mouse over the different variables - the IDE will tell you what they contain. As mentioned, the d variable will have it's default value, but let's change that, by moving forward in the execution. In the next post, I will show you how to navigate around your code, while it's being executed.

Monday, 1 December 2014

C#.NET Tutorial - Day - 21- Debugging - Introduction to Debugging


INTRODUCTION TO DEBUGGING



When you get past the most basic "Hello world!" examples, your code will reach a level of complexity where you can't necessarily figure out what's going on just by running it. What you need, is some black magic, which allows you to open the virtual hood of your application while it's running and see what's going on. Debugging is that magical tool, and as soon as you learn the most basic steps of it, you will wonder how you ever lived without it. It's a tool that every good programmer should understand, simply because it's almost impossible to fix bugs in complex code without it. 

The most basic type of debugging, which is still being used by even advanced programmers, is sometimes called "print debugging" - a simple procedure, where you make your application print a piece of text or a number somewhere, allowing you to see which part of your code has been reached and what your variables contain. With C#, you can use the Console.Write() method, to output the contents of a variable or a simple status message, which will be printed to the console. That can be enough for some situations, but if you're using a nice IDE like Visual Studio or one of the Express versions, you have much stronger tools to your disposal, and they are every bit as easy to use, once you learn the most basic principles. In the next couple of posts, we will guide you through the debugging possibilities of your IDE and after that, you will be a much stronger programmer.



Sunday, 30 November 2014

C#.NET Tutorial - Day - 20 - Classes - Interfaces


INTERFACES



In previous posts, we had a look at abstract classes. Interfaces are much like abstract classes and they share the fact that no instances of them can be created. However, interfaces are even more conceptual than abstract classes, since no method bodies are allowed at all. So an interface is kind of like an abstract class with nothing but abstract methods, and since there are no methods with actual code, there is no need for any fields. Properties are allowed though, as well as indexers and events. You can consider an interface as a contract - a class that implements it is required to implement all of the methods and properties. However, the most important difference is that while C# doesn't allow multiple inheritance, where classes inherit more than a single base class, it does in fact allow for implementation of multiple interfaces! 

So, how does all of this look in code? Here's a pretty complete example. Have a look, perhaps try it out on your own, and then read on for the full explanation: 



 


Let's start in the middle, where we declare the interface. As you can see, the only difference from a class declaration, is the keyword used - interface instead of class. Also, the name of the interface is prefixed with an I for Interface - this is simply a coding standard, and not a requirement. You can call your interfaces whatever you want, but since they are used like classes so much that you might have a hard time telling the difference in some parts of your code, the I prefix makes pretty good sense. 

Then we declare the Describe method, and afterwards, the Name property, which has both a get and a set keyword, making this a read and writeable property. You will also notice the lack of access modifiers (public, private, protected etc.), and that's because they are not allowed in an interface - they are all public by default. 

Next up is our Dog class. Notice how it looks just like inheriting from another class, with the colon between the class name and the class/interface being subclassed/implemented. However, in this case, two interfaces are implemented for the same class, simply separated by a comma. You can implement as many interfaces as you want to, but in this case we only implement two - our own IAnimal interface, and the .NET IComparable interface, which is a shared interface for classes that can be sorted. Now as you can see, we have implemented both the method and the property from the IAnimal interface, as well as a CompareTo method from the IComparable interface. 

Now you might be thinking: If we have to do all the work our self, by implementing the entire methods and properties, why even bother? And a very good example of why it's worth your time, is given in the top of our example. Here, we add a bunch of Dog objects to a list, and then we sort the list. And how does the list know how to sort dogs? Because our Dog class has a CompareTo method that can tell how to compare two dogs. And how does the list know that our Dog object can do just that, and which method to call to get the dogs compared? Because we told it so, by implementing an interface that promises a CompareTo method! This is the real beauty of interfaces.

Saturday, 29 November 2014

C#.NET Tutorial - Day - 19 - Classes - More Abstract Classes


MORE ABSTRACT CLASSES



In the previous post, we had a look at abstract classes. In this post, we will expand the examples a bit, and throw in some abstract methods as well. Abstract methods are only allowed within abstract classes. Their definition will look like a regular method, but they have no code inside them: 




So, why would you want to define an empty method that does nothing? Because an abstract method is an obligation to implent that very method in all subclasses. In fact, it's checked at compile time, to ensure that your subclasses has this method defined. Once again, this is a great way to create a base class for something, while still maintaining a certain amount of control of what the subclasses should be able to do. With this in mind, you can always treat a subclass as its baseclass, whenever you need to use methods defined as abstract methods on the baseclass. For instance, consider the following example: 



































As you can see, we create an ArrayList to contain our animals. We then instantiate a new dog and a new cat and add them to the list. They are instantiated as a Dog and a Cat respectively, but they are also of the type FourLeggedAnimal, and since the compiler knows that subclasses of that class contains the Describe() method, you are actually allowed to call that method, without knowing the exact type of animal. So by typecasting to the FourLeggedAnimal, which is what we do in the foreach loop, we get access to members of the subclasses. This can be very useful in lots of scenarios.



Friday, 28 November 2014

C#.NET Tutorial - Day - 18 - Classes - Abstract Classes


ABSTRACT CLASSES



Abstract classes, marked by the keyword abstract in the class definition, are typically used to define a base class in the hierarchy. What's special about them, is that you can't create an instance of them - if you try, you will get a compile error. Instead, you have to subclass them, as taught in the post on inheritance, and create an instance of your subclass. So when do you need an abstract class? It really depends on what you do. 

To be honest, you can go a long way without needing an abstract class, but they are great for specific things, like frameworks, which is why you will find quite a bit of abstract classes within the .NET framework it self. A good rule of thumb is that the name actually makes really good sense - abstract classes are very often, if not always, used to describe something abstract, something that is more of a concept than a real thing. 

In this example, we will create a base class for four legged animals and then create a Dog class, which inherits from it, like this:





If you compare it with the examples in the post about inheritance, you won't see a big difference. In fact, the abstract keyword in front of the FourLeggedAnimal definition is the biggest difference. As you can see, we create a new instance of the Dog class and then call the inherited Describe() method from the FourLeggedAnimal class. Now try creating an instance of the FourLeggedAnimal class instead:





You will get this fine compiler error: 

Cannot create an instance of the abstract class or interface 'AbstractClasses.FourLeggedAnimal' 

Now, as you can see, we just inherited the Describe() method, but it isn't very useful in it's current form, for our Dog class. Let's override it:





In this case, we do a complete override, but in some cases, you might want to use the behavior from the base class in addition to new functionality. This can be done by using the base keyword, which refers to the class we inherit from:





Now obviously, you can create other subclasses of the FourLeggedAnimal class - perhaps a cat or a lion? In the next post, we will do a more advanced example and introduce abstract methods as well. Read on.



Thursday, 27 November 2014

C#.NET Tutorial - Day - 17 - Classes - Inheritance


INHERITANCE



One of the absolute key aspects of Object Oriented Programming (OOP), which is the concept that C# is built upon, is inheritance, the ability to create classes which inherits certain aspects from parent classes. The entire .NET framework is built on this concept, with the "everything is an object" as a result of it. Even a simple number is an instance of a class, which inherits from the System.Object class, although .NET helps you out a bit, so you can assign a number directly, instead of having to create a new instance of e.g. the integer class. 

This subject can be a bit difficult to comprehend, but sometimes it help with some examples, so let's start with a simple one of those:




First, we define an Animal class, with a simple method to output a greeting. Then we define a Dog class, and with a colon, we tell C# that the Dog class should inherit from the Animal class. The beautiful thing about this is that it makes sense in the real world as well - a Dog is, obviously, an Animal. Let's try using the classes:




If you run this example, you will notice that even though we have not defined a Greet() method for the Dog class, it still knows how to greet us, because it inherits this method from the Animal class. However, this greeting is a bit anonymous, so let's customize it when we know which animal it is:




Besides the added method on the Dog class, you should notice two things: I have added the virtual keyword to the method on the Animal class, and on the Dog class, I use the override keyword. 

In C#, you are not allowed to override a member of a class unless it's marked as virtual. If you want to, you can still access the inherited method, even when you override it, using the base keyword.




Methods is not the only thing to get inherited, though. In fact, pretty much all class members will be inherited, including fields and properties. Just remember the rules of visibilty, as discussed in a previous post. 

Inheritance is not only from one class to another - you can have a whole hierarchy of classes, which inherits from eachother. For instance, we could create a Puppy class, which inherits from our Dog class, which in turn inherits from the Animal class. What you can't do in C#, is to let one class inherit from several other classes at the same time. Multiple inheritance, as it's called, is not supported by C#.




Tuesday, 25 November 2014

C#.NET Tutorial - Day - 16 - Classes - Static Members


STATIC MEMBERS




As we saw in a previous post, the usual way to communicate with a class, is to create a new instance of the class, and then work on the resulting object. In most cases, this is what classes are all about - the ability to instantiate multiple copies of the same class and then use them differently in some way. However, in some cases, you might like to have a class which you may use without instantiating it, or at least a class where you can use members of it without creating an object for it. For instance, you may have a class with a variable that always remains the same, no matter where and how it's used. This is called a static member, static because it remains the same. 



A class can be static, and it can have static members, both functions and fields. A static class can't be instantiated, so in other words, it will work more as a grouping of related members than an actual class. You may choose to create a non-static class instead, but let it have certain static members. A non-static class can still be instantiated and used like a regular class, but you can't use a static member on an object of the class. A static class may only contain static members. 

First, here is an example of a static class:




As you can see, we use the static keyword to mark the class as static, and then we use it again to mark the method, CalculateArea, as static as well. If we didn't do that, the compiler would complain, since we can't have a non-static member of a static class. 

To use this method, we call it directly on the class, like this:




We could add other helpful methods to the Rectangle class, but perhaps you are wondering why we are passing on width and height to the actual method, instead of storing it inside the class and then pulling them from there when needed? Because it's static! We could store them, but only one set of dimensions, because there is only one version of a static class. This is very important to understand. 

Instead, we can make the class non-static, and then have the CalculateArea as a utility function on this class:




As you can see, we have made the class non-static. We have also added a constructor, which takes a width and a height and assigns it to the instance. Then we have added an OutputArea method, which uses the static method to calculate the area. This is a fine example of mixing static members with non-static members, in a non-static class. 

A common usage of static classes, although frowned upon by some people, are utility/helper classes, where you collect a bunch of useful methods, which might not belong together, but doesn't really seem to fit elsewhere either.



C#.NET Tutorial - Day - 15 - Classes - Visibility


VISIBILITY



The visibility of a class, a method, a variable or a property tells us how this item can be accessed. The most common types of visibility are private and public, but there are actually several other types of visibility within C#. Here is a complete list, and although some of them might not feel that relevant to you right now, you can always come back to this page and read up on them: 

PUBLIC - the member can be reached from anywhere. This is the least restrictive visibility. Enums and interfaces are, by default, publicly visible. 

PROTECTED - members can only be reached from within the same class, or from a class which inherits from this class. 

INTERNAL - members can be reached from within the same project only. 

PROTECTED INTERNAL - the same as internal, except that also classes which inherits from this class can reach it members, even from another project. 

PRIVATE - can only be reached by members from the same class. This is the most restrictive visibility. Classes and structs are by default set to private visibility. 

So for instance, if you have two classes, Class1 and Class2, private members from Class1 can only be used within Class1. You can't create a new instance of Class1 inside of Class2, and then expect to be able to use its private members. 

If Class2 inherits from Class1, then only non-private members can be reached from inside of Class2.



Monday, 24 November 2014

C#.NET Tutorial - Day - 14 - Classes - Method Overloading


METHOD OVERLOADING



A lot of programming languages supports a technique called default/optional parameters. It allows the programmer to make one or several parameters optional, by giving them a default value. It's especially practical when adding functionality to existing code. 

For instance, you may wish to add functionality to an existing function, which requires one or more parameters to be added. By doing so, you would break existing code calling this function, since they would now not be passing the required amount of parameters. To work around this, you could define the newly added parameters as optional, and give them a default value that corresponds to how the code would work before adding the parameters. 

Default parameters were introduced in C# version 4.0, but up until that, C# coders have been using a different technique, which basically does the same, called method overloading. It allows the programmer do define several methods with the same name, as long as they take a different set of parameters. When you use the classes of the .NET framework, you will soon realize that method overloading is used all over the place. A good example of this, is the Substring() method of the String class. It is with an extra overload, like this:





 You can call it with either one or two parameters. If you only call it with one parameter, the length parameter is assumed to be the rest of the string, saving us time whenever we simply want to get the last part of a string. 

So, by defining several versions of the same function, how do we avoid having the same code several places? It's actually quite simple: We let the simple versions of the method make the complex version of it do all the work. Consider the following example:





We define a Plus method, in two different versions. The first one takes two paramaters, for adding two numbers, while the second version takes three numbers. The actual work is done in the version that takes three numbers - if we only wish to add two, we call the three parameter version, and simply use 0 as the third paramater, acting as a default value. I know, I know, it's a silly example, as indicated by the name of the class, but it should give you an idea about how it all works. 

Now, whenever you feel like doing advanced math by adding a total of four numbers (just kidding here), it's very simple to add a new overload:





The cool thing about this, is that all your existing calls to the Plus method will continue working, as if nothing had been changed. The more you use C#, the more you will learn to appreciate method overloading.




Sunday, 23 November 2014

C#.NET Tutorial - Day - 13 - Classes - Constructors & Destructors


CONSTRUCTORS & DESTRUCTOR



CONSTRUCTORS



Constructors are special methods, used when instantiating a class. A constructor can never return anything, which is why you don't have to define a return type for it. A normal method is defined like this:




A constructor can be defined like this:





In our example for this post, we have a Car class, with a constructor which takes a string as argument. Of course, a constructor can be overloaded as well, meaning we can have several constructors, with the same name, but different parameters. Here is an example:





A constructor can call another constructor, which can come in handy in several situations. Here is an example:





If you run this code, you will see that the constructor with no parameters is called first. This can be used for instantiating various objects for the class in the default constructor, which can be called from other constructors from the class. If the constructor you wish to call takes parameters, you can do that as well. Here is a simple example:





If you call the constructor which takes 2 parameters, the first parameter will be used to invoke the constructor that takes 1 parameter. 




DESTRUCTORS



Since C# is garbage collected, meaing that the framework will free the objects that you no longer use, there may be times where you need to do some manual cleanup. A destructor, a method called once an object is disposed, can be used to cleanup resources used by the object. Destructors doesn't look very much like other methods in C#. Here is an example of a destructor for our Car class:





Once the object is collected by the garbage collector, this method is called.



Saturday, 22 November 2014

C#.NET Tutorial - Day - 12 - Classes - Properties


PROPERTIES



Properties allow you to control the accessibility of a classes variables, and is the recommended way to access variables from the outside in an object oriented programming language like C#. In our post on classes, we saw the use of a property for the first time, and the concept is actually quite simple. A property is much like a combination of a variable and a method - it can't take any parameters, but you are able to process the value before it's assigned to our returned. A property consists of 2 parts, a get and a set method, wrapped inside the property:






The get method should return the variable, while the set method should assign a value to it. Our example is as simple as it gets, but it can be extended. Another thing you should know about properties is the fact that only one method is required - either get or set, the other is optional. This allows you to define read-only and write-only properties. Here is a better example of why properties are useful:




Okay, we have just made our property a bit more advanced. The color variable will now be returned in uppercase characters, since we apply the ToUpper() method to it before returning it, and when we try to set the color, only the value "Red" will be accepted. Sure, this example is not terrible useful, but it shows the potential of properties.



Thursday, 20 November 2014

C#.NET Tutorial - Day - 11 - Classes - Introduction to C# Classes


INTRODUCTION TO C# CLASSES



In lots of programming tutorials, information about classes will be saved for much later. However, since C# is all about Object Oriented programming and thereby classes, we will make a basic introduction to the most important stuff already now. 



First of all, a class is a group of related methods and variables. A class describes these things, and in most cases, you create an instance of this class, now referred to as an object. On this object, you use the defined methods and variables. Of course, you can create as many instances of your class as you want to. Classes, and Object Oriented programming in general, is a huge topic. We will cover some of it in this chapter as well as in later chapters, but not all of it. 

In the Hello world chapter, we saw a class used for the first time, since everything in C# is built upon classes. Let's expand our Hello world example with a class we built on our own.




Okay, lots of new stuff here, but almost all of it is based on stuff we've already used earlier in this tutorial. As you can see, we have defined a new class, called Car. It's declared in the same file as our main application, for an easier overview, however, usually new classes are defined in their own files. It defines a single variable, called color, which of course is used to tell the color of our car. We declared it as private, which is good practice - accessing variables from the outside should be done using a property. The Color property is defined in the end of the class, giving access to the color variable. 

Besides that, our Car class defines a constructor. It takes a parameter which allows us to initialize Car objects with a color. Since there is only one constructor, Car objects can only be instantiated with a color. The Describe() method allows us to get a nice message with the single piece of information that we record about our. It simply returns a string with the information we provide. 

Now, in our main application, we declare a variable of the type Car. After that, we create a new instance of it, with "Red" as parameter. According to the code of our class, this means that the color red will be assigned as the color of the car. To verify this, we call the Describe() method, and to show how easy we can create several instances of the same class, we do it again, but with another color. We have just created our first functional class and used it. 

In the following chapters, concepts like properties, constructors and visibility will be explained in more depth.



Wednesday, 19 November 2014

C#.NET Tutorial - Day - 10 - The Basics - Arrays


ARRAYS


Arrays works as collections of items, for instance strings. You can use them to gather items in a single group, and perform various operations on them, e.g. sorting. Besides that, several methods within the framework work on arrays, to make it possible to accept a range of items instead of just one. This fact alone makes it important to know a bit about arrays. 

Arrays are declared much like variables, with a set of [] brackets after the datatype, like this:




You need to instantiate the array to use it, which is done like this:




The number (2) is the size of the array, that is, the amount of items we can put in it. Putting items into the array is pretty simple as well:




But why 0? As it is with so many things in the world of programming, the counting starts from 0 instead of 1. So the first item is indexed as 0, the next as 1 and so on. You should remember this when filling the array with items, because overfilling it will cause an exception. When you look at the initializer, setting the array to a size of 2, it might seem natural to put item number 0, 1 and 2 into it, but this is one item too much. If you do it, an exception will be thrown. We will discuss exceptions in a later post. 

Earlier, we learned about loops, and obviously these go great with arrays. The most common way of getting data out of an array, is to loop through it and perform some sort of operation with each value. Let's use the array from before, to make a real example:




We use the foreach loop, because it's the easiest, but of course we could have used one of the other types of loop instead. The for loop is good with arrays as well, for instance if you need to count each item, like this:




It's actually very simple. We use the Length property of the array to decide how many times the loop should iterate, and then we use the counter (i) to output where we are in the process, as well as get the item from the array. Just like we used a number, a so called indexer, to put items into the array, we can use it to get a specific item out again. 

I told you earlier that we could use an array to sort a range of values, and it's actually very easy. The Array class contains a bunch of smart methods for working with arrays. This example will use numbers instead of strings, just to try something else, but it could just as easily have been strings. I wish to show you another way of populating an array, which is much easier if you have a small, predefined set of items that you wish to put into your array. Take a look:




With one line, we have created an array with a size of 5, and filled it with 5 integers. By filling the array like this, you get an extra advantage, since the compiler will check and make sure that you don't put too many items into the array. Try adding a number more - you will see the compiler complain about it. 

Actually, it can be done even shorter, like this:





This is short, and you don't have to specify a size. The first approach may be easier to read later on though. 

Let's try sorting the array - here's a complete example:





The only real new thing here is the Array.Sort command. It can take various parameters, for various kinds of sorting, but in this case, it simply takes our array. As you can see from the result, our array has been sorted. The Array class has other methods as well, for instance the Reverse() method. You can look it up in the documentation to see all the features of the Array class. 

The arrays we have used so far have only had one dimension. However, C# arrays can be multidimensional, sometimes referred to as arrays in arrays. Multidimensional arrays come in two flavors with C#: Rectangular arrays and jagged arrays. The difference is that with rectangular arrays, all the dimensions have to be the same size, hence the name rectangular. A jagged array can have dimensions of various sizes. Multidimensional arrays are a heavy subject, and a bit out of the scope of this tutorial.