Differences Between C And Visual Basic


Differences Between C# And Visual Basic

Beyond the obvious syntactical differences between these two languages, there are really two key concepts with which you have to familiarize yourself to progress from Visual Basic to C#:

  1. The concept of the complete flow of execution of a program from start to finish: Visual Basic hides this aspect of programs from you, so that the only elements of a Visual Basic program you code are the event handlers and any methods in class modules. C# makes the complete program available to you as source code. The reason for this has to do with the fact that C# can be seen, philosophically, as next-generation C++. The roots of C++ go back to the 1960s and predate windowed user interfaces and sophisticated operating systems. C++ evolved as a low-level, close- to-the-machine, all-purpose language. To write GUI applications with C++ meant that you had to invoke the system calls to create and interact with the windowed forms. C# has been designed to build on this tradition while simplifying and modernizing C++, to combine the low-level performance benefits of C++ with the ease of coding in Visual Basic. Visual Basic, on the other hand, is designed specifically for rapid application development of Windows GUI applications. For this reason, in Visual Basic all the GUI boilerplate code is hidden, and all the Visual Basic programmer implements are the event handlers. In C# on the other hand, this boilerplate code is exposed as part of your source code.

  2. Classes and inheritance: C# is a genuine object-oriented language, unlike Visual Basic, requiring all code to be a part of a class. It also includes extensive support for implementation inheritance. Indeed, most well-designed C# programs will be very much designed around this form of inheritance, which is completely absent in Visual Basic.

The bulk of this appendix is devoted to developing two sample applications. The first example is a simple form, written in both Visual Basic and C#, that asks the user for a number and displays the square root and sign of the number. By comparing the Visual Basic and C# versions of the sample in some detail, you will learn basic C# syntax and also understand the concepts behind the flow of execution of a program.

Next, you are presented with a Visual Basic class module that stores information about employees and its C# equivalent. This example demonstrates the real power of C# by showing you the shortcomings of Visual Basic.

The appendix finishes with a short tour of some of the remaining differences between Visual Basic and C#.

Before you start, however, a couple of concepts require some clarification: classes, compilation, and the.NET base classes.

Classes

Throughout this appendix, you use C# classes quite extensively. C# classes represent precisely defined objects (see Chapter 3, "Objects and Types," and Appendix A, "Principles of Object-Oriented Programming"). However, for the purposes here, you are better off thinking of them as the C# equivalent to Visual Basic class modules, because they are quite similar entities: Like a Visual Basic class module, a C# class implements properties and methods, and contains member variables. Like a Visual Basic class module, you can create objects of a given C# class (class instances) using the operator new. Beyond these similarities, however, there are many differences. For example, a Visual Basic class module is really a COM class. C# classes, by contrast, are always integrated into the .NET Framework. C# classes are also more lightweight than their Visual Basic or COM counterparts, in the sense that they are designed for performance and give a smaller performance hit when instantiated. However, for the most part these differences will not affect the discussion of the C# language here.

Compilation

As you know, computers never directly execute code in any high-level language, whether it is Visual Basic, C++, C, or any other language. Instead, all source code is first translated into native executable code, a process usually known as compilation. When you are debugging, Visual Basic offers the option of just running the code (meaning that each line of Visual Basic code is interpreted as the computer executes that line), or of doing a full compile (meaning that the entire program is first translated into executable code, and then execution starts). Performing a full compile first means that any syntax errors are discovered by the compiler before the program starts running. It also yields much higher performance when running and is therefore the only option permitted in C#.

In C#, compilation is done in two stages. First, code is complied into the Microsoft intermediate language (IL), a process commonly referred to as compilation. Then the code is converted into native executable code at runtime. This is not the same as interpreting. Entire portions of code are converted from IL to assembly language at a time and the resultant native executable is then stored so it doesn't need to be recompiled the next time that portion of code is executed. Combined with various optimizations, Microsoft believes that this will ultimately lead to code that is actually faster to execute than with the previous system of compiling direct from source code to native executable. Although the existence of IL is something that you need to bear in mind, it won't affect the discussion in this appendix, because it doesn't really affect C# language syntax.

The .NET Base Classes

Visual Basic has a large number of associated functions, such as the conversion functions CInt, CStr, and so on, the file system functions, date-time functions, and many more. Visual Basic also relies on the presence of ActiveX controls to provide the standard controls that you put on your form, such as list boxes, buttons, text boxes, and so on.

C# also relies on extensive support for these sorts of areas. However, in the case of C#, this support comes from a very large set of classes known as the .NET base classes. These classes provide support for almost every aspect of Windows development. There are classes that represent all the standard controls, classes that perform conversions, classes that perform date-time and file system access, classes that access the Internet, and many more. This appendix won't go into the .NET base class library in detail, but it will frequently refer to it. Indeed, C# is so well integrated with the .NET base classes that many C# keywords just provide wrappers around particular base classes. In particular, all the basic C# data types that are used to represent integers, floating-point numbers, strings, and so on are actually base classes.

In this respect, there is a marked distinction between Visual Basic and C#; the Visual Basic system functions are specific to Visual Basic, whereas the respective functionality of C# is provided by the .NET base classes, which are accessible to any .NET-aware language.

Conventions

This appendix frequently compares code in C# and Visual Basic. To make it easier to identify code in these two languages, C# code is presented in this format:

// C# code that we have already seen   // C# code that we want to draw attention to or which is new  

However, all Visual Basic code is presented in this format:

' Visual Basic code is presented with a white background

Example: The Square Root Form

In this section, you examine a simple application called SquareRoot, which has been developed in both Visual Basic and C#. The application is a simple dialog box that asks the user to type in a number, and then, when the user clicks a button, displays the sign and square root of that number. If the number is negative, the square root needs to be displayed as a complex number, which means taking the square root of the number and adding "i" after it. Figure B-1 shows the C# version of this example. The Visual Basic version is pretty much identical in appearance except that it has a standard Visual Basic icon in place of the .NET Windows Forms icon in the top-left corner.

image from book Figure B-1

SquareRoot Visual Basic Version

To get this application working in Visual Basic, you simply need to add an event handler for the event of clicking the button. The button has been given the name cmdShowResults, and the TextBox controls have the intuitive names of txtNumber, txtSign, and txtResult. With these names, the event handler for the button looks like this:

Option Explicit Private Sub cmdShowResults_Click()    Dim sngNumberInput As Single    sngNumberInput = CSng(Me.txtNumber.Text)    If (sngNumberInput < 0) Then       Me.txtSign.Text = "Negative"       Me.txtResult.Text = CStr(Sqr(-sngNumberInput)) & " i"    ElseIf (sngNumberInput = 0) Then       txtSign.Text = "Zero"       txtResult.Text = "0"    Else       Me.txtSign.Text = "Positive"       Me.txtResult.Text = CStr(Sqr(sngNumberInput))    End If End Sub

That is all the Visual Basic code that you need to write.

SquareRoot C# Version

In C# you also need to write an event handler for the event of the button being clicked. You keep the same names for the button and the text boxes, but in C# the code looks like this:

 // Event handler for user clicking Show Results button. // Displays square root and sign of number private void OnClickShowResults(object sender, System.EventArgs e) { float NumberInput = float.Parse(this.txtNumber.Text); if (NumberInput < 0) { this.txtSign.Text = "Negative"; this.txtResult.Text = Math.Sqrt(-NumberInput).ToString() + " i"; } else if (NumberInput == 0) { txtSign.Text = "Zero"; txtResult.Text = "0"; } else { this.txtSign.Text = "Positive"; this.txtResult.Text = Math.Sqrt(NumberInput).ToString (); } } 

Comparing these two code samples, you can see the similarity in the code structure, and even without any knowledge of C#, you can probably get some idea of what is going on. It is also evident that a huge number of differences exist in the syntax between the two languages. Over the next couple of pages, you compare these samples to see what you can learn about C# syntax in the process. In the process, you will also uncover some of the differences between the basic methodologies of C# and Visual Basic.

Basic Syntax

This section examines the two SquareRoot programs to see what they teach you about C# syntax.

C# requires all variables to be declared

If you start with the first line of Visual Basic code, you encounter the Option Explicit declaration. This statement has no equivalent in C#. The reason is that in C# variables must always be declared before they are used. It's as if C# always runs with Option Explicit turned on and doesn't allow you to switch it off. Hence there's no need to declare Option Explicit. The point of this restriction is that C# has been very carefully designed to make it difficult for you to accidentally introduce bugs into your code. Standard advice in Visual Basic is always to use Option Explicit because it prevents hard-to- find bugs caused by misspelled variable names. Generally, you will find that C# doesn't allow you to do things that have a high risk of causing bugs.

Comments

Because commenting code is always important, the next thing you do in both samples (or the first thing in the C# sample!) is add a comment:

 // Event handler for user clicking Show Results button. // Displays square root and sign of number private void OnClickShowResults(object sender, System.EventArgs e) { 

In Visual Basic you use an apostrophe to denote the start of a comment, and the comment lasts until the end of the line. The C# comments in the code work the same way, except they start with two forward slashes: //. Just as for Visual Basic comments, you can use an entire line for a comment or append a comment to the end of a line:

 // This code works out the results int Result = 10*Input;   // get result 

However, C# is more flexible in its comments because it allows two other ways of indicating comments, and each has a slightly different effect. A comment may be also be delimited by the sequences /* and */. In other words, if the compiler sees an opening /* sequence, it assumes all the following text is a comment until it sees a closing */ sequence. This allows you to have long, multiple-line comments:

 /* this text is a really long long long long comment */ 

Short comments within a line are very useful if you just want to temporarily swap something in a line while you are debugging:

 X = /*20*/ 15; 

The third option is very similar to the first option. However, now you use three forward slashes:

 /// <summary> /// Event handler for user clicking Show Results button. /// Displays square root and sign of number /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnClickShowResults(object sender, System.EventArgs e) 

If you use three forward slashes instead of two, the comment still lasts until the end of that line. However, this comment now has an additional effect: The C# compiler is actually capable of using comments that start with three slashes to automatically generate documentation for your source code as a separate XML file. That's why the comment text in the previous example appears to have a fairly formal structure — it is ready to be placed into an XML file. We won't go into the details of this process here (it's covered in Chapter 2, "C# Basics"). We will, however, say that this means that commenting each method of your code allows you to have complete documentation automatically generated and updated when you modify your code. The compiler even checks that the documentation matches the method signatures.

Statement separation and grouping

The most visible difference between the preceding C# and Visual Basic code is the presence of semicolons and curly braces in the C# code. Although this can make C# code look daunting, the principle is actually very simple. Visual Basic uses carriage returns to indicate the ends of statements, whereas C# uses semicolons for the same purpose. In fact, the C# compiler completely ignores all excess whitespace, including carriage returns. These features of C# syntax can combine to give you a lot of freedom in laying out your code. For example, the following snippet (reformatted from part of the preceding sample) is also perfectly valid C# code:

             this.txtSign.Text = "Negative"; this.txtResult.Text = Math.Sqrt (-NumberInput) + " i"; 

Obviously, if you want other people to be able to read your code, you will opt for the first coding style, and Visual Studio 2005 will automatically lay out your code in that style.

The braces are used to group statements together into what are known as block statements (or compound statements). This is a concept that doesn't exist in Visual Basic. In C#, you can group any statements by placing braces around them. The group is now regarded as one single block statement and can be used anywhere in C# where a single statement is expected.

Block statements are used a lot in C#. For example, in the previous C# code there is no explicit indication of the end of the OnClickShowResults() method (C# has methods, written in text with the () appended, whereas Visual Basic has functions and subs). Visual Basic needs an End Sub statement at the end of any sub because a sub can contain as many statements as you want, so a specific marker is the only way that Visual Basic knows where you intend the sub to end. C# works differently. In C# a method is formed from exactly one compound statement. Because of this, the method ends with the closing curly brace matching the opening one at the start of the method.

You find this a lot in C#: where Visual Basic uses some keyword to mark the end of a block of code, C# simply organizes the block into one compound statement. The if statement in the previous samples illustrates the same point. In Visual Basic, you need an End If statement to mark where the If block ends, if the If statement is more than one line. In C#, the rule is simply that an if clause always contains exactly one statement, and the else clause also contains one statement. If you want to put more than one statement into either clause, as is the case in the previous example, you use a compound statement.

Capitalization

One other point you may notice about the syntax is that all the keywords — if, else, int, and so on — in the C# code are in lowercase.

Important

Remember that unlike Visual Basic, C# is case-sensitive.

In C#, if you write If instead of if, the compiler won't understand your code. One advantage of being case-sensitive, however, is that you can have two variables whose names differ only in case, such as Name and name. You'll encounter this in the second sample application later in this appendix.

In general, you'll find that all C# keywords are entirely lowercase.

Methods

Compare the syntax that Visual Basic and C# use to declare the part of the code that handles the event:

Private Sub cmdShowResults_Click()

and:

 private void OnClickShowResults(object sender, System.EventArgs e)  

The Visual Basic version declares a sub, whereas the C# version declares a method. In Visual Basic, code is traditionally grouped into subs and functions, with the concept of a procedure being either. Additionally, Visual Basic class objects have what are known as methods, which for all practical purposes means the same thing as procedures except that they are part of a class module.

C#, by contrast, only has methods (that's because everything in C# is part of a class). C# does not support the concept of functions and subroutines; these terms don't even exist in the C# language specification. In Visual Basic, the only real difference between a sub and a function is that a sub never returnsa value. In C#, if a method does not need to return a value, it is declared as returning void (as the OnClickShowResults() method illustrated earlier).

The syntax for declaring a method is similar in the two languages, at least to the extent that the parameters follow the method name in brackets. Note, however, that whereas in Visual Basic declaring a sub is indicated with the word Sub, there is no corresponding word in the C# version. In C#, the return type(void in this case), followed by the method name, followed by the opening bracket, is sufficient to tell the compiler that you are declaring a method, because no other construct in C# has this syntax (arrays in C# are marked with square rather than round brackets so there is no risk of confusion with arrays).

Like the Visual Basic Sub, the C# method declaration in the preceding code is preceded by the keyword private. This has roughly the same meaning as in Visual Basic — it prevents outside code from being able to see the method. (You'll examine the notion of outside code shortly.)

There are two other differences to remark on about the method declaration: the C# version takes two parameters, and it has a different name from the Visual Basic event handler.

The name of the event handler in Visual Basic is supplied for you by the Visual Basic IDE. The reason that Visual Basic knows that the Sub is the event handler for a button click is because of the name, cmdShowResults_Click. If you renamed the sub, it wouldn't get called when you click the button. However, C# doesn't use the name in this way. In C#, there is some other code that tells the compiler which method is the event handler for this event. That means you can give the handler whatever name you want. However, something starting with On for an event handler is traditional, and in C#, common practice is to name methods (and for that matter most other items) using Pascal casing, which means that words are joined together with their first letters capitalized. Using underscores in names in C# is not recommended, and the example uses a name in accordance with these guidelines: OnClickShowResults().

Now for the parameters. You don't need to worry about the details of these parameters in this appendix. All you need to know for now is that all event handlers in C# are required to take two parameters similar to these, and these parameters can provide some useful extra information about the event in question (for example, for a mouse move event the parameters might indicate the location of the mouse pointer).

Variables

The SquareRoot sample can tell you quite a lot about the differences between the variable declarations in C# and Visual Basic. In the Visual Basic version, you declare a floating-point number and set up its value as follows:

Dim sngNumberInput As Single sngNumberInput = CSng(Me.txtNumber.Text) 

The C# version looks like this:

 float NumberInput = float.Parse(this.txtNumber.Text); 

As you'd expect, the data types in C# aren't exactly the same as in Visual Basic. float is the C# equivalent to Single. It's probably easier for you to understand what's going on if you split up the C# version into two lines. The following C# code has exactly the same effect as the preceding line:

 float NumberInput; NumberInput = float.Parse(this.txtNumber.Text); 

Now you can compare the declaration and initialization of the variable separately.

Declarations

The obvious syntactical difference between C# and VB6, as far as variable declarations are concerned, is that in C#, the data type precedes rather than follows the name of the variable, with no other keywords. This gives C# declarations a more compact format than their Visual Basic counterparts.

You'll notice that this idea of a declaration consisting only of a type followed by a name is used elsewhere too. Look again at the method declaration in C#:

 private void OnClickShowResults(object sender, System.EventArgs e) 

The type (void) precedes the name of the method, with no other keywords to indicate what you are declaring — that's obvious from the context. The same is also true for the parameters. The types of the parameters are object and System.EventArgs. The object type in C# plays a similar role to Object in Visual Basic — it indicates something for which you are choosing not to specify its type. However, the C# object type is much more powerful than the Visual Basic Object. In C#, object also replaces VB6's Variant data type. You'll look at object later on. System.EventArgs is not covered in any detail in this appendix. It's a .NET base class, and it has no equivalent in Visual Basic.

In the case of variables, the declaration syntax used in C# allows you to combine the declaration with the setting of an initial value for the variable. In the code sample sngNumberInput is initialized to what looks like a complicated expression, which is explained shortly. To take two simpler examples:

 int X = 10; // int is similar to Long in Visual Basic string Message = "Hello World"; // string is similar to String in Visual Basic  

While we are on the subject, you should know a couple of other points about variables.

No suffixes in C#

Visual Basic allows you to attach suffixes to variables to indicate their data types, with $ for String, % for Int, and & for Long:

Dim Message$ ' will be a string

This syntax is not supported in C#. Variable names may contain only letters, numbers, and the underscore character, and you must always indicate the data type.

No default values for local variables

In the Visual Basic code sample, the variable sngNumberInput is assigned the default value of 0 when it is declared. This is actually a waste of processor time because you immediately assign it a new value in the next statement. C# is a little more performance-conscious and does not bother putting any default values in local variables when they are declared. Instead, it requires that you always initialize such variables yourself before you use them. The C# compiler will raise a compilation error if you attempt to read the value in any local variable before you have set it.

Assigning values to variables

Assigning values to variables in C# is done with the same syntax as in VB6. You simply put an = sign after the variable name, followed by the value you are assigning to it. However, one point to watch out for is that this is the only syntax used in C#. In some cases in Visual Basic, you use Let, whereas for objects, Visual Basic always uses the Set keyword:

Set MyListBox = new ListBox

C# does not use a separate syntax for assigning to object references. The C# equivalent of the preceding is:

 MyListBox = new ListBox(); 
Important

Remember that in C#, variables are always assigned using the syntax <VariableName>=<Expression>;

Classes

Here you look at what's going on in the expression used to initialize the variable sngNumberInput in the SquareRoot sample. The C# and Visual Basic examples are both doing exactly the same thing: They grab the text from the txtNumber TextBox control; but the syntax is different:

sngNumberInput = CSng (Me.txtNumber.Text) 

and:

 float NumberInput = float.Parse(this.txtNumber.Text); 

Getting the value out of the TextBox controls is quite similar in both cases. The only difference here is the syntax: Visual Basic uses the keyword Me whereas C# uses the keyword this, which has exactly the same meaning (in fact, in C# you can omit this if you want, just as you can omit Me in Visual Basic). In C# you could equally well have written:

 float NumberInput = float.Parse(txtNumber.Text); 

The more interesting part is how the string retrieved from the TextBox control is converted to a float (or single), because this illustrates a fundamental point of the C# language, which was hinted at earlier: everything in C# is part of a class.

In Visual Basic, the conversion is carried out by a function, CSng. However, C# does not have functions of the Visual Basic variety. C# is totally object-oriented and will only allow you to declare methods that are part of a class.

In C#, the conversion from string to float is carried out by the Parse() method. However, because Parse() is part of a class, it has to be preceded by the name of the class. The class against which you need to call the Parse() method is float. Yes, I did say that right. Up until now float has been treated as simply being the C# equivalent to the Visual Basic Single type. However, it is actually a class as well. In C#, all data types are classes as well, which means even things like int, float, and string have methods and properties that you can call (although you should know that int and float are special types of class known in C# as structs. The difference is not important for the code here but it is explained later).

Note

If you are looking really carefully at the code, you might notice a slight apparent problem with the analogy with Visual Basic class modules. In Visual Basic, you call methods by specifying the name of an object, not the name of the class module, but you've called Parse by specifying the name of the class, float, instead of the name of an object. Parse() is a special type of method known as a static method. It has no equivalent in Visual Basic, and a static method can be called without creating an instance of a class. Hence you specify the class name, float, rather than a variable name. By the way, static does not have the same meaning in C# as it does in Visual Basic. There is no equivalent in C# to the Visual Basic static variables — there is no need for these in the C# object-oriented programming methodology, because you use C# fields in their stead.

Note

Also, to be strictly accurate, it should be pointed out that the name of the class is actually System. Single, not float. System.Single is one of the .NET base classes, and C# uses the keyword float to indicate this class.

If Statements

Next you come to the main part of the event handler — the "If" statement. Recall that the Visual Basic version looks like this:

If (sngNumberInput < 0) Then    Me.txtSign.Text = "Negative"    Me.txtResult.Text = CStr(Sqr(-sngNumberInput)) & " i" ElseIf (sngNumberInput = 0) Then    txtSign.Text = "Zero"    txtResult.Text = "0" Else Me.txtSign.Text = "Positive"    Me.txtResult.Text = CStr(Sqr(sngNumberInput)) End If

In the C# version, it looks like this:

 if (NumberInput < 0)  { this.txtSign.Text = "Negative"; this.txtResult.Text = Math.Sqrt(-NumberInput).ToString() + " i"; } else if (NumberInput == 0)  { txtSign.Text = "Zero"; txtResult.Text = "0"; } else { this.txtSign.Text = "Positive"; this.txtResult.Text = Math.Sqrt(NumberInput).ToString(); } 

You have already learned the biggest syntactical difference here: that each part of the if statement in C# must be a single statement; hence, if you have to conditionally execute more than one statement, you must combine them into a single block statement. In C#, if there is only one statement to be conditionally executed, you don't need to form a block statement. For example, if you want to skip setting the text in the txtSign TextBox control in the preceding code, you can write:

 if (NumberInput < 0) this.txtResult.Text = Math.Sqrt(-NumberInput) + " i"; else if (NumberInput == 0) txtSign.Text = "Zero"; else this.txtResult.Text = Math.Sqrt(NumberInput).ToString(); 

Other syntax differences worth noting include the following: In C#, the parentheses around the condition to be tested in an if statement are compulsory. In Visual Basic you could have written:

If sngNumberInput < 0 Then

Trying the same trick in C# would result in a compilation error. In general, C# is much pickier about the syntax it expects than Visual Basic. Also, notice that when you test whether NumberInput is zero, you use two equals signs in succession for the comparison:

 else if (NumberInput == 0) 

In Visual Basic, the symbol = has two purposes: it is used for assigning values to variables and for comparing values. C# formally recognizes these as two very different types of operation, and so uses different symbols: = for assignment and == for comparison.

There is one other important difference that you should be aware of, because this one can easily catch you by surprise when making the transition from Visual Basic to C#: else if is two words in C# whereas it is one word in Visual Basic: ElseIf.

Calculating square roots: Another class method

Given the earlier comments about everything in C# being a member of the class, you won't be surprised to learn that C#'s equivalent of the Visual Basic Sqr function, which calculates square roots, is also a method that is a member of a class. In this case, it is the Sqrt() method, which is a static member of another .NET base class, System.Math, which you can abbreviate to just Math in your code.

Note also that when dealing with the condition of the number input being exactly zero, you don't specify the this keyword in the C# code:

 txtSign.Text = "Zero";  txtResult.Text = "0"; 

In the corresponding Visual Basic code, you don't specify Me explicitly either. In C#, just as in Visual Basic, you don't have to explicitly specify this (Me) unless the context is unclear.

Strings

To display the square root of a negative number, you use string processing:

 this.txtResult.Text = Math.Sqrt(-NumberInput).ToString() + " i"; 

Note that in C# concatenation of strings is done using the symbol + rather than &. Note also that you convert from a float to a String by calling a method on the float object. The method is called ToString(), and this method is not static, so it is called using the same syntax as in Visual Basic when you call methods on objects: by prefixing the name of the method with the name of the variable that represents the object, followed by a dot. One useful thing to remember about C# is that every object (and hence every variable) inherits the ToString() functionality and can provide its own custom method.

Extra Code in C#

The comparison of the event handler routines in C# and Visual Basic is now complete. In the process, you've learned a lot about the syntactical differences between the languages. In fact, you have learned most of the basic syntax that C# uses to piece statements together. You have also had your first brush with the fact that everything in C# is a class. However, if you have downloaded the sample code for these samples from the Wrox Press Web site (www.wrox.com) and looked at the code, you will have almost certainly noticed that we have carefully avoided any discussion of the most obvious difference between the samples: there is a lot more code in the C# sample than simply an event handler. For the Visual Basic version of the SquareRoot sample, the code for the event handler presented here represents the total of all the source code in the project that is visible to you. However, in the C# version of the project, this event handler is just one method in a large source code file that contains a lot more code.

The reason why there is so much additional code in the C# project has to do with the fact that the Visual Basic IDE hides a lot of what's going on in your program from you. In Visual Basic, all you needed to write was the event handler, but in fact the sample is doing a lot more. It needs to start up, display the form on the screen, send information to Windows regarding what it wants to do with events, and shut it down when you have finished. In Visual Basic, you don't have access to any of the code that does this. By contrast, C# takes a completely different approach and leaves all this code in the open. That might make your source code look more complicated, but it does have the advantage that if the code is available, then you can edit it, which means you gain much more flexibility in deciding how your application should behave.

What Happens When You Run a Program

Any program involves a precise sequence of execution. When an application is launched the computer comes across an instruction that identifies the start of the program. It will then carry on executing the next instruction, and the next, and the next, and so on. Some of these commands will tell the computer to jump to a different instruction, depending on the values contained in certain variables, for example. Very often the computer will jump back and execute the same instructions again. However, there is always this continuous sequence of executing the next instruction until the computer comes across a command that tells it to terminate the execution of the code. This linear sequence is true of any program. Some programs may be multithreaded, in which case there are several sequences of execution (threads). However, each thread still follows this sequence from an initial instruction through to termination of the program.

Of course, this sequence is not what you see when you write a Visual Basic executable program. In Visual Basic, what you write is essentially a set of event handlers or subs, each of which is called when the user does something. There's typically no single start to the program, although the Form_Load event handler comes close to that in concept. Even so, Form_Load is really only another event handler. It just happens to be the handler for the event that gets raised when the form is loaded, which means it'll be the first event that runs. Similarly, if, instead of an executable, you are writing a control or a class object, you don't have a start point. You simply write a class and add lots of methods and properties to it. Each method or property will execute when the client code calls it.

Note

Note also that in Visual Basic, Sub Main does exist, and acts as the entry point to a program, but unlike the Main() method of C#, Sub Main is optional.

To see how you can relate the two programming ideas, take a look at what actually happens when any Visual Basic application — or for that matter any Windows GUI application, no matter what language it is written in — executes. This is a bit more restrictive than the applications mentioned before, because now you are focusing on Windows GUI applications (in other words, not consoles, services, and so on).

As usual, execution starts at some well-defined point. The commands executed probably involve the creation of some Windows and controls, and displaying those controls on the screen. At that point, the program then does something that is known as entering a message loop. What effectively happens is that the program puts itself to sleep and tells Windows to wake it up when something interesting happens that it needs to know about. These "interesting" things are the events that you have written handlers for, and also a good few events that you haven't written your own event handlers for, because even if you don't write a handler for a particular event, the Visual Basic IDE may quietly supply one for you. A good example of this is the handlers that deal with resizing a form. You never see the source code for this in Visual Basic, but a Visual Basic application is still able to respond correctly when the user attempts to resize the form because the Visual Basic IDE has invisibly added event handlers to your project to correctly handle this situation.

Whenever an event occurs, Windows wakes up the application and calls the relevant event handler — that's when the code that you wrote might start executing. When the event handler subroutine exits, the application puts itself to sleep again, once again telling Windows to wake it up when another interesting event happens. Finally, assuming nothing goes wrong, at some point Windows will wake up the application and inform it that it needs to shut down. At that point, the application takes any appropriate action — for example, displaying a message box asking users if they want to save a file — and then terminates itself. Again, most of the code to do this has been quietly added to your project behind the scenes by the Visual Basic IDE, and you never get to see it.

Figure B-2 sows the thread of execution in a typical Windows GUI application.

image from book
Figure B-2

In Figure B-2, the box with a dashed border indicates the part of execution that the Visual Basic IDE lets you get access to, and for which you can write source code: some of the event handlers. The rest of the code is inaccessible to you, though you can specify it to some extent through your choice of application type when you first ask Visual Basic to create a project. Recall that when you create a new project in Visual Basic, you get a dialog box asking you what type of application you want to create: Standard EXE, ActiveX EXE, ActiveX DLL, and so on. After you make your selection, the Visual Basic IDE uses your choice to generate all the appropriate code for the part of the program that is outside the dashed box in Figure B-2. The diagram shows the situation when you choose to create a Standard EXE project and will differ for other types of project (for example, an ActiveX DLL doesn't have a message loop at all but relies on clients to call the methods instead), but it should give you a rough idea of what's going on.

In C# you can view (if not modify) the code that does everything. All the nitty-gritty details of things, such as what's going on inside the message loop, are hidden inside various DLLs that Microsoft has written, but you do get to see the high-level methods that call up the various bits of processing. So, for example, you have access to the code that starts up the program, the call to a library method that makes your program enter the message loop and puts it to sleep, and so on. You also get access to the source code that instantiates all the various controls you place on your form, makes them visible, and sorts out their initial positions and sizes, and all the rest. You don't need to write any of this code yourself. When you use Visual Studio 2005 to create a C# project, you will still get a dialog box asking you which type of project you want to create, and Visual Studio will still write all the background code for you. The difference is that Visual Studio writes this background code as source C# code, which then becomes code that you can edit directly.

Doing things this way does, as mentioned, bloat your source code. However, the huge advantage is that you have much more flexibility in what your program does and how it behaves. It also means that you can write many more types of projects in C#. Whereas in Visual Basic, the only things you can write are different kinds of form, and COM components, in C# you can write any of the different types of programs that run on Windows.

The C# Code for the Rest of the Program

This section discusses the rest of the code for the SquareRoot sample. In the process you will learn a bit more about classes in C#.

Note

The C# SquareRoot sample was created in Visual Studio 2005, and the Visual Basic one was created in the Visual Basic 6 IDE. However, the code presented here isn't quite what Visual Studio generated for us. Apart from adding the event handler, a couple of other tweaks have been made to the code in order to better illustrate the principles of C# programming. However, it will still give you a good idea of the sort of work that Visual Studio does when it creates a project for you.

The full text of the source code is quite long. It will not be presented here; you can find it in the accompanying document, VBToCSharp_CSharpSource.pdf.

Namespaces

The main part of the C# SquareRoot source code begins with a couple of namespace declarations and a class declaration:

 namespace Wrox.ProCSharp.VbToCSharp.SquareRootSample { public class SquareRootForm : System.Windows.Forms.Form { 

The SquareRootForm class holds almost all the code with the exception a small amount of code that is contained in the class MainEntryClass. Remember that it's easiest here to think of a C# class resembling a Visual Basic class object, with the exception that you can see the source code that begins the declaration of the class. The Visual Basic IDE only gives you a separate window with the contents of the class in it.

A namespace is something that doesn't really have an analogy in Visual Basic, and the easiest way to think of it is as a way of organizing the names of your classes in much the same way as a file system organizes the names of your files. For example, you almost certainly have a number of files on your hard drive all called ReadMe.Txt. If that name, ReadMe.Txt, were the only information you had about each file, you'd have no way of distinguishing between them all. However, you can distinguish between them using their full pathnames; for example, on my computer one of them is actually C:\Program Files\ReadMe.txt and another is G:\Program Files\HTML Help Workshop\ReadMe.txt.

Namespaces work in the same way, but without all the overhead of having an actual file system — they are basically no more than labels. You don't have to do anything to create a namespace, other than declare it in your code in the way you've done in the preceding sample. The preceding code means that the full name of the class you have defined is not SquareRootForm, but Wrox.ProCSharp.VbToCSharp. SquareRootSample.SquarRootForm. It is extremely unlikely that anyone else will write a class with that full name. On the other hand, if you didn't have the namespace, there would be more risk of confusion because someone else might conceivably write a class called SquareRootForm.

Avoiding clashes in this way is important in C#, because the .NET environment uses only these names to identify classes, whereas the ActiveX controls created by Visual Basic used a complex mechanism involving GUIDs to avoid name clashes. Microsoft has opted for the simpler concept of namespaces because of concerns that some of the complexities of COM, such as GUIDs, made it unnecessarily difficult for developers to write good Windows applications.

In C#, although namespaces are not strictly required, it is strongly advised that you place all your C# for classes in a namespace in order to prevent any possible name clashes with other software. In fact, it is quite rare to see C# code that does not start with a namespace declaration, and namespaces are an excellent method to organize related classes into logical order.

Namespaces can be nested. For example, this namespace code

 namespace Wrox.ProCSharp.VbToCSharp.SquareRootSample {  public class SquareRootForm : System.Windows.Forms.Form  {  // and so on }  }  

could have been written like this:

 namespace Wrox  { namespace ProCSharp  {  namespace VbToCSharp { namespace SquareRootSample { public class SquareRootForm : System.Windows.Forms.Form { // and so on } } } }  } 

In this code, the closing curly braces are added just to emphasize that they always have to match up. Curly braces are used to mark the boundaries of namespaces and classes just as they are used to mark the boundaries of methods and compound statements.

The using directive

The final part of the code that begins the SquareRoot project consists of using directives:

 using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; namespace Wrox.ProCSharp.VbToCSharp.SquareRootSample { 

These using directives are here to simplify the code. Full names of classes, including the namespace names, are long. For example, later in this code you will be defining a couple of text boxes. A TextBox control is represented by the class System.Windows.Forms.TextBox. If you had to write that in your code every time you wanted to refer to TextBox, your code would look very messy. Instead, the statement using System.Windows.Forms; instructs the compiler to look in this namespace for any classes that are not in the current namespace, and for which you have not specified a namespace. Now you can simply write TextBox whenever you want to refer to that class. It is common to start any C# program with a number of using directives that bring in all the namespaces you are going to use into the set of namespaces searched by the compiler. The namespaces specified in the previous code are all namespaces that cover various parts of the .NET base-class library, and so allow you to conveniently use various.NET base classes.

The class definition: Inheritance

Now you come to the definition of the SquareRootForm class. The definition itself is fairly simple:

 public class SquareRootForm : System.Windows.Forms.Form  { 

The keyword class tells the compiler that you are about to define a class. The interesting part is the colon after the name of the class, which is followed by another name, Form. This is the point at which you need to bring in that other important C# concept mentioned earlier: inheritance.

What the previous code does is tell the compiler that the SquareRootForm class inherits from the class Form (actually System.Windows.Forms.Form). What this means is that the class has not only any methods, properties, and so on that you define; it also inherits everything that was in Form. Form is an extremely powerful .NET base class, which gives you all the features of a basic form. It contains methods that get the form to display itself, and a large number of properties including Height, Width, Desktop Location, and BackColor (the background color of the form), which control the appearance of the form on the screen. By inheriting from this class, your own class gets all these features as well, and is therefore already a fully fledged form. The class you inherit from is known as the base class, and the new class is known as the derived class.

If you have worked with interfaces before, the concept of inheritance will not be new to you. What you have here, however, is much more powerful than interface inheritance. When a COM interface inherits from another interface, it only gets what the interface contains — the names and signatures of the methods and properties. However, a class contains all the code that implements these methods and so on as well, just as in Visual Basic a class object does. This means that SquareRootForm gets all the implementations of just about everything in Form, as well as the method names. This kind of inheritance is known as implementation inheritance and is not new to C#: It has been a fundamental concept of classic object-oriented programming (OOP) for decades. C++ and Java programs, in particular, use this concept extensively, but it was not supported in Visual Basic. (Implementation inheritance does have similarities to subclassing.) As you get used to writing C# programs, you will find that the entire architecture of a typical C# program is almost invariably based around implementation inheritance.

But implementation inheritance is even more powerful than that. As you will see later on, when a class inherits from another class, it doesn't have to take all the implementations of everything in the base class. If you want, you can modify the implementations of particular methods and properties using a technique called overriding. This means that you can create a class that is very similar to an existing class, but has some differences in how it works or what it does. That makes it very easy for you to reuse code that other people have written, thereby saving yourself a lot of development time. It is also important to understand that you don't need access to the source code of the base class in order to derive from it. For obvious commercial reasons, Microsoft is keeping the source code of Form to itself. The fact that the compiled library is available in the form of an assembly is sufficient for you to be able to inherit from the class, taking those methods you want and overriding those that you don't want.

Program Entry Point

You now jump to near the end of the sample code, to examine the main program entry point. That is the Main() function, reproduced here:

 class MainEntryClass { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { SquareRootForm TheMainForm = new SquareRootForm(); Application.Run(TheMainForm); } } 

This doesn't look at first sight like a very obvious program entry point, but it is. The rule in C# is that program execution starts at a method called Main(). This method must be defined as a static method in some class. There can normally be only one Main() method throughout all the classes in the source code — otherwise the compiler won't know which one to choose, without further compilation switches. Main() here is defined as not taking any parameters and returning void (in other words, not returning anything). This isn't the only possible signature for the method, but it is the usual one for a Windows application (command-line applications may take parameters; these are any command-line arguments you specify).

Because Main() has to be in a class, you've put it in one: a class called MainEntryClass. Although this class doesn't contain anything else, it's legitimate for a class that contains the main entry point to contain other methods as well. The fact that Main() is a static method is important. Recall that static methods can be run without actually creating an object of the class first. Because the very first thing that happens when the program is run is that Main() is called, there aren't yet any instances of any classes, hence the entry point has to be static.

Apart from the static keyword, the definition of Main() looks much like the earlier method definition you examined. However, it is prefixed by the word [STAThread] in square brackets. STAThread is an example of an attribute — another concept that has no equivalent in Visual Basic source code.

An attribute is something that provides extra information to the compiler about some item in the code, and always takes the form of a word (possibly with some parameters as well, though not in this case) in square brackets, immediately before the item to which it applies. This particular attribute tells the compiler about the threading model that the code needs to run in. Without going into details, note that writing [STAThread] in the C# source code has a similar effect to selecting the threading model under Project Properties in the Visual Basic IDE, although in Visual Basic you can only do this for ActiveX DLL and ActiveX Control projects.

This comparison shows once again the different philosophy of C# compared to Visual Basic. In Visual Basic, the threading model is there and needs to be specified, but it is all but hidden by the Visual Basic IDE, so you can't get to it in the Visual Basic source code — in Visual Basic you have to access it through the project settings.

Instantiating Classes

Now let's examine the code inside the Main() method. The first thing you need to do is create the form, that is, instantiate a SquareRootForm object. This is dealt with by the first line of code:

 SquareRootForm TheMainForm = new SquareRootForm(); 

You obviously can't compare this with the corresponding Visual Basic code, because the corresponding Visual Basic commands aren't available as source code, but you can do a comparison — if you imagine that in some Visual Basic code you are going to create a dialog box. In VB6, the way you would do that would look something like this:

Dim SomeDialog As MyDialogClass  Set SomeDialog = New MyDialogClass

In this Visual Basic code, you first declare a variable that is an object reference: SomeDialog refers to a MyDialogClass instance. Then you actually instantiate an object using the Visual Basic New keyword and set your variable to refer to it.

That's exactly what is going on in the C# code too: you declare a variable called TheMainForm, which is a reference to a SquareRootForm object; then you use the C# new keyword to create an instance of SquareRootForm, and set your variable to refer to it. The main syntactical difference is that C# allows you to combine both operations into one statement, in the same way that you were previously able to declare and initialize the NumberInput variable in one go. Note also the parentheses after the new expression. That is a requirement of C#. When creating objects, you always have to write these brackets in. The reason is that C# treats creating an object a bit like a method call, to the extent that you can even pass parameters into the call to new, to indicate how you want the new object to be initialized. In this case, you don't pass in any parameters, but you still need the parentheses.

C# classes

So far you've seen that C# classes are similar to class modules in Visual Basic. You've already seen one difference in that C# classes allow static methods. The code for the Main() method now highlights another difference. If you were doing something like this in Visual Basic, you would also need to set the object created to Nothing when you have finished with it. However, nothing like that appears in the C# code, because in C# it is not necessary to do this. That's because C# classes are more efficient and lightweight than their Visual Basic counterparts. Visual Basic class objects are really COM objects, which means they include some sophisticated code that checks how many references to the object are being held, so that each object can destroy itself when it detects it is no longer needed. In Visual Basic, if you don't set your object reference to Nothing when you have finished with the object, this is considered bad practice because it means the object does not know that it is no longer needed, so it can stay in memory, possibly until the whole process ends.

However, for performance reasons, C# objects don't perform this kind of checking. Instead, C# makes use of the .NET garbage collection mechanism. What happens is that, instead of each object checking whether it should still be alive, every so often the .NET runtime hands control to the garbage collector. The garbage collector examines the state of memory, uses a very efficient algorithm to identify those objects that are no longer referenced by your code, and removes them. Because of this mechanism, it is not considered important that you reset references when you have finished with them — it is normally sufficient to simply wait until the variable goes out of scope.

If, however, you do want to set reference variables not to refer to anything, then the relevant C# keyword is null, which is identical to Nothing in Visual Basic. Hence, where in Visual Basic you would write

Set SomeDialog = Nothing

in C# you would write something like:

 TheMainForm = null; 

Note, however, that this by itself doesn't achieve much in C# unless the variable TheMainForm still has a substantial lifetime left, because the object won't be destroyed until the garbage collector is called up.

Entering the message loop

Now consider the final statement in the Main() method:

 Application.Run(TheMainForm); 

This statement is the one that enters the message loop. What you are actually doing is calling a static method of the class System.Windows.Forms.Application. The method in question is the Run() method. This method handles the message loop. It puts the application (or strictly speaking, the thread) to sleep and requests Windows to wake it up whenever an interesting event occurs. The Run() method can take one parameter, which is a reference to the form that handles all events. Run() exits when an event instructing the form to terminate has occurred and been handled.

After the Run() method has exited, there is nothing else to be done, so the Main() method returns. Because this method was the entry point to the program, when it returns, execution of the entire process stops.

One piece of syntax in the preceding statements that you might find surprising is that you use parentheses when calling the Run() method, even though you are not using any return value from this method, and hence you are doing the equivalent of calling a Visual Basic sub. In this situation, Visual Basic does not require parentheses, but the rule is that in C# you always use parentheses when calling any method.

Important

Always use parentheses in C# when calling any method, whether or not you are going to use any return value.

The SquareRootForm Class

You have now seen how C# enters a message loop, but you have not yet seen the process of displaying and creating the form itself, and the text has also been rather vague about the calling of the event handlers. You have seen that Windows calls event handlers, such as the OnClickButtonResults() method. But how does Windows know that that is the method to be called? You can find the answers to those questions in the SquareRootForm class definition, and in its base class, Form.

First, note that the SquareRootForm class has quite a number of member fields. (Member field is C# parlance for a variable that is defined as a member of a class. You can think of it as being like a Visual Basic variable that has form scope, or alternatively as being like a Visual Basic variable that is defined as a member of a class module. Each such variable is associated with a particular instance of a class — a particular object — and stays in scope for as long as its containing object remains alive.)

 public class SquareRootForm : System.Windows.Forms.Form { private System.Windows.Forms.TextBox txtNumber; private System.Windows.Forms.TextBox txtSign; private System.Windows.Forms.TextBox txtResult; private System.Windows.Forms.Button cmdShowResults; private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label4; 

These fields each correspond to one of the controls. You can see clearly the three TextBox and the Button controls, as well as the four Label controls, corresponding to the areas of text on the form. You won't be doing anything with the labels so there's no need to give them more user-friendly names.

However, each of these variables is just a reference to an object, so the fact that these variables exist doesn't imply any instances of these objects exist — the objects have to be instantiated separately. The process of instantiating these controls is done in a constructor. A constructor in C# is analogous to Visual Basic subs such as Form_Load, Form_Initialize, and Class_Initialize. It is a special method that is automatically called whenever an instance of the class is created, and it contains whatever code is needed to initialize the instance.

You can spot the constructor in the class because a constructor always has the same name and casing as the class itself. In this case you just look for a method called SquareRootForm:

 public SquareRootForm() { InitializeComponent(); } 

Note that because this is a constructor, not a method, that you can call, it doesn't have any return type specified. It does, however, have parentheses after its name just like a method. You can use these parentheses to specify parameters to be passed to the constructor (you can pass parameters in the parentheses after the new clause when creating a variable). The definition of the constructor indicates if any parameters are needed to create an instance of the object. However, you don't have any parameters in this example; they are included in the Employee code sample later in the appendix.

In this case the constructor just calls a method, InitializeComponent(). This is because of Visual Studio 2005. Visual Studio has the same set of features as the Visual Basic IDE for manipulating controls graphically — clicking to place controls on the form and so on. However, because now with C# the definitions of all the controls are set out in the source code, Visual Studio 2005 has to be able to read the source code to find out what controls are around on your form. It does this by looking for an InitializeComponent() method, and seeing what controls are instantiated there.

InitializeComponent() is a huge method, so you won't look at it all, but it starts off like this:

 private void InitializeComponent() { this.txtNumber = new System.Windows.Forms.TextBox();  this.txtSign = new System.Windows.Forms.TextBox();  this.cmdShowResults = new System.Windows.Forms.Button();  this.label3 = new System.Windows.Forms.Label();  this.label4 = new System.Windows.Forms.Label();  this.label1 = new System.Windows.Forms.Label();  this.label2 = new System.Windows.Forms.Label();  this.txtResult = new System.Windows.Forms.TextBox(); 

The previous code is a set of calls to actually instantiate all the controls on the form. This snippet doesn't really contain any new pieces of C# syntax. The next part of the code starts setting properties on the controls:

 //  // txtNumber  // this.txtNumber.Location = new System.Drawing.Point(160, 24);  this.txtNumber.Name = "txtNumber";  this.txtNumber.TabIndex = 0;  this.txtNumber.Text = ""; //  // txtSign  //  this.txtSign.Enabled = false;  this.txtSign.Location = new System.Drawing.Point(160, 136);  this.txtSign.Name = "txtSign";  this.txtSign.TabIndex = 1;  this.txtSign.Text = "";  

This code sets up the start positions and initial text of two of the controls, the input TextBox control and the TextBox control that displays the sign of the number input. One new bit of code is that the location relative to the top-left corner of the screen is specified using a Point. Point is a .NET base class (in fact, a struct) that stores x and y coordinates. The syntax for the two lines that set the Location is instructive. The TextBox.Location property is just a reference to a Point, so in order to set it to a value you need to create and initialize a Point object that holds the correct coordinates. This is the first time that you've seen a constructor that takes parameters — in this case, the horizontal and vertical coordinates of the Point and hence of the control. If you'd wanted to translate one of these lines into Visual Basic, assuming you'd defined some Visual Basic class module called Point, and you had a class that had such a property, the best you would be able to do would look something like this:

Dim Location As Point  Set Location = New Point  Location.X = 160  Location.Y = 24  SomeObject.Location = Location 

Compare this to the C# code:

 someObject.Location = new System.Drawing.Point(160, 24); 

The relative compactness and readability of the equivalent C# statement should be obvious! Now look at the same commands for the button. In this case, you see the same kinds of properties being set up, but here there is one other thing that needs to be done: you need to tell Windows to call your event handler when the button is clicked. The line that does this is shown in bold:

 this.cmdShowResults.Name = "cmdShowResults";  this.cmdShowResults.Size = new System.Drawing.Size(88, 23);  this.cmdShowResults.TabIndex = 3;  this.cmdShowResults.Text = "Show Results";  this.cmdShowResults.Click += new System.EventHandler(this.OnClickShowResults);  

What's going on here is this: The button, which is referred to by the cmdShowResults button object, contains an event, Click, that will be raised when the user clicks the button. You need to add your event handler to this event. Now C# doesn't allow you to pass names of methods around directly; instead you have to wrap them up into something called a delegate. This is done to ensure type safety (see Chapter 6, "Delegates and Events"), and is the reason for the new System.EventHandler() text in the code. Once you've wrapped the name of the event handler up, you add it to the event using an operator +=, which is discussed next.

Arithmetic assignment operators

The += symbol represents what is known as the addition-assignment operator in C#. It provides a convenient shorthand for cases where you want to add some quantity to another quantity. How it works is this. Say, in Visual Basic you had declared two Integers, A and B, and you were going to write

B = B + A

In C# the equivalent type is int, and you can write something very similar:

 B = B + A; 

However, in C#, there is an alternative shorthand for this:

 B += A; 

+= really means "add the expression on the right to the variable on the left," and it works for all the numeric data types, not just int. Not only that but there are other similar operators, *=, /=, and -= which respectively multiply, divide, and subtract the quantity on the left by the one on the right. So for example, to divide a number by 2, and assign the result back to B, you'd write:

 B /= 2; 

C# has other operators that represent bitwise operations, as well as % that takes the remainder on division — and almost all of these have corresponding operation assignment operators (see Chapter 2, "C# Basics").

In the SquareRootForm sample, you have simply applied the addition assignment operator to an event; the line

 this.cmdShowResults.Click += new System.EventHandler(this.OnClickShowResults); 

simply means "add this handler to the event."

Note that operators like +, -, *, and so on in Visual Basic only have meaning when applied to numeric data. In C#, however, they can be applied to any type of object.

The previous statement needs to be qualified a bit. In order to be able to apply these operators to other types of objects, you have to first tell the compiler what these operators mean for other types of objects — a process known as operator overloading. Suppose you want to write a class that represented a mathematical vector. In Visual Basic you write a class module, and then add:

Dim V1 As Vector Set V1 = New Vector

In mathematics, it's possible to add vectors, which is where operator overloading comes in. But Visual Basic doesn't support operator overloading, so instead in Visual Basic you'd probably define a method, Add, on the Vector, so you could do this:

' V1, V2, and V3 are Vectors  Set V3 = V1.Add(V2)

In Visual Basic, that's the best you can do. However, in C#, if you define a Vector class, you can add an operator overload for + to it. The operator overload is basically a method that has the name operator +, and which the compiler will call up if it sees + applied to a Vector. That means that in C# you are able to write:

 // V1, V2 and V3 are Vectors  V3 = V1 + V2; 

Chapter 5, "Operators and Casts," details the code for overloading such a Vector class, and discusses operator overloading in more detail.

Obviously you wouldn't want to define operator overloads for all classes. For most classes that you write, it wouldn't make sense to do things like add or multiply objects together. However, for the classes for which it does make sense to do this, operator overloads can go a long way toward making your code easier to read. That's what has happened with events. Because it makes sense to talk about adding a handler to an event, an operator overload has been supplied to let you do this using the intuitive syntax using the + (and +=) operators. You can also use or -= to remove a handler from an event.

You've really gone as far as you can go with the SquareRootForm code samples. There is a lot more C# code that you haven't examined in the C# version of this application, but this extra code has largely to do with setting up the various other controls on the form, and doesn't introduce any new principles.

Up to now, you've had a flavor of the syntax of C#. You've seen how it lets you write statements in a way that is often much shorter than the corresponding Visual Basic code. You have also seen the way that C# places all the code in the source file, unlike Visual Basic, where much of the background code is hidden from you — something that makes your code simpler at the cost of reducing your flexibility in the kinds of applications you can write. You've also had your first hints at the concepts behind inheritance.

However, what you have not yet seen is a real example of some code that you can write in C#, where it would be extremely hard to write Visual Basic code to achieve the same result. You are going to see an example of this in the next code sample, in which you write a couple of classes that illustrate the kinds of things you can do with inheritance.




Professional C# 2005
Pro Visual C++ 2005 for C# Developers
ISBN: 1590596080
EAN: 2147483647
Year: 2005
Pages: 351
Authors: Dean C. Wills

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net