Monkeys at Keyboards: The Javanomicon
© Michael James Heron
Topic: Java Programming
Level: 2
Version: delta

For of those to whom much is given, much is required. And when at some future date the high court of history sits in judgement on each of us, recording whether in our brief span of service we fulfilled our responsibilities to the state, our success or failure, in whatever office we hold, will be measured by the answers to four questions - First, were we truly men of courage... Second, were we truly men of judgement... Third, were we truly men of integrity... Finally were we truly men of dedication?
John F. Kennedy

34 - Moving from Java to C#

PreviousTable of ContentsNext
Forum


Chapter Objectives

By the end of this chapter, the reader will be able to:

  • write C# programs!


34.1

Introduction

Way back at the beginning of this text I mentioned that this is not a book about Java. We then proceeded to look at nothing else for hundreds of pages. This chapter is intended to give you an overview of how much you actually know that can be applied to other programming languages - in this case, the C# programming language from Microsoft.

Programming isn't about the language in which you write your code - it's all about the way you think about problems. Once you become competent in one programming language, there is a much easier learning curve when you move to another. In the case of the transition between C# and Java, the inherent commonalties of the language make it especially easy process - but when it comes to learning how to code in a language that is not syntactically or philosophically similar to anything with which you are currently familiar, you'll still find it a much easier task.

At the time of writing, Java maintains a clear lead over C# in terms of its suitability as an introductory / professional programming language. C# is still playing 'catch-up' in terms of the power of the language and the market share it commands. Is C# the future? Only time will tell. But you should feel confident that you are well equipped to deal with whatever the future has in store!

34.2

The .NET Framework

The .NET Framework is Microsoft's next generation development platform. It borrows heavily from many aspects of other programming languages to provide a range of tools for approaching almost any programming task.

Microsoft spokespeople have said that the future success of the company rests with the success of the .NET framework. If that fails, so too will Microsoft. Whether this is a good thing or not is a matter for debate, but there is no doubt that Microsoft is committed to pushing the platform into prominence as a first-class development environment.

At its core, .NET is an integrated platform for development that is comprised of three main components:

  • The Common Language Runtime (CLR)
  • The .NET Framework Classes
  • ASP.NET

The Framework itself is largely language independent - you can write code in any supported language and then combine it with the code you wrote in an entirely different supported language.

The key to all of this lies in the Common Language Runtime, which shares more than a few similarities in term of architecture with the Java Virtual Machine. Code written for the .NET framework is compiled into what is called Intermediate Language (IL), which is then run via the medium of the Common Language Runtime on the host system. This is an extension of what Java does - a Java compiler takes a Java file and compiles it into byte code which then gets executed on the Java Virtual Machine.

The Common Language Runtime also performs the tasks you'd expect the JVM to perform, such as ensure a solid strategy for security and garbage collection.

The big improvement offered by .NET is that many languages can be compiled to IL, meaning that there is no need to learn the syntax of a language other than the one you're most used to - if you're familiar with Visual Basic, then you can use Visual Basic .NET to write your code. If you're more of a C++ person, then you can make use of C++.NET.

All of these languages have access to the .NET Framework Classes, providing a common theme of functionality throughout them. These are very similar to the classes provided as standard in the Java API, and in fact you'll find all of the things you know and love from Java - ArrayLists, HashMaps, and more. The .NET Framework is comprehensive and provides a number of tools that allow you to concentrate on developing software rather than on reinventing the wheel.

ASP.NET is a delivery platform, and allows developers to use multiple languages (C# and Visual Basic .NET primarily) to deliver internet-based applications. This greatly reduces the complexity of web-based development by providing many of the utility classes that are lacking in other internet development languages.

So that's a quick overview of what all the fuss is about.

34.3

What is C#?

C# is a new language provided by Microsoft to harness the power of the .NET framework. Syntactically it shares a lot with Java since they have a common heritage in C and C++. Microsoft claim C# is an evolution of C++, but regardless of the fact it's never spoken aloud by Microsoft, it has more similarities with Java than it has differences.

Let's have a look at the similarities by starting off with a 'hello world' program in C#:

using System; 

public class Class1 {

public static void Main (string[] args) {
Console.WriteLine ("Argh, it burns!");
}

}

Looks pretty similar, doesn't it? Let's list the lines one by one:

Line by Line Analysis
Fig 34.1: Line by Line Analysis

So far so good - our first C# program and we've seen absolutely nothing new in it. The syntax is a little bit different, but not so much so that it renders us confused and unable to understand. The difference in naming conventions is one of the biggest difficulties in coming to terms with C#, but that gets easier with practise.

using System; 

public class Class1 {

public static void Main (string[] args) {
int[] bing = { 1, 2, 3, 4, 5, 6, 7, 8 };
foreach (int i in bing) {
Console.WriteLine (i);
}

}

}

There are some other syntactical differences, which we'll discuss as and when we encounter them.

34.4

Event Driven Programming in C#

Usually the development of a C# program is done via a builder IDE, such as Visual Studio. However, it is perfectly possible to write code that requires only a text editor, in the same way it is possible to write code for Java with nothing more sophisticated than WordPad. The process of setting up a user interface is similar to the equivalent process in Java, although a little bit more complicated:

using System; 
using System.Drawing;
using System.Windows.Forms;
public class ExampleGUI :
Form {
Button myButton;

public ExampleGUI() {
myButton = new Button();
myButton.Text = "Press Me!";
myButton.Location = new Point (100, 100);
myButton.Size = new Size (75, 50);
this.Controls.Add (myButton);
myButton.Click +=new EventHandler (Pressed_Button);
}


public void Pressed_Button (object ob, EventArgs e) {
MessageBox.Show ("You pressed the button, ""you dirty little button presser!"
, "Dirty little button presser.");
}


public static void Main (string[] args) {
Application.Run (new ExampleGUI());
}

}

Note that the class definition has a strange syntax:

public class ExampleGUI : Form

There is nothing mystical going on here - this is just C#'s syntax for declaring an inherited relationship - the colon takes the place of the extends keyword in Java. Like Java, C# provides single level inheritance and interfaces only... an inheritance is specified with the colon symbol.

The process of setting up a component is again similar to what we've done in the past. First, we create a variable to hold the component:

Button myButton; 

Then we create an object that will go into that variable:

myButton = new Button(); 

We have to set the text that will appear on the button - notice here that we're not using a method to do this. We'll talk about how this works in a few moments:

myButton.Text = "Press Me!"; 

Then we need to set where the component is going to appear:

myButton.Location = new Point (100, 100); 
myButton.Size = new Size (75, 50);

This is effectively our setBounds method. The Point object we create has an X and Y co-ordinate, and the Size object has a width and height:

Once we've configured our component, we add the button to the form:

this.Controls.Add (myButton); 

And then optionally register a listener object:

myButton.Click += new EventHandler (Pressed_Button); 

This is where things start to get a little different from the way Java deals with event handling. We choose exactly which events we want to register a listener for - we don't just register interest in whole families of events. Once we've selected which event we want to handle, we create a new EventHandler object, passing into its constructor method the name of the method we want to be executed when an event of that type is triggered. We don't have to handle it all within a single actionPerformed method.

Our event handling code is likewise similar, except that the first argument that gets passed to the method we specify is the object that triggered the event - we don't need to use getSource to find it:


public void Pressed_Button (object ob, EventArgs e) {
MessageBox.Show ("You pressed the button, ""you dirty little button presser!"
, "Dirty little button presser.");
}

The MessageBox class handles message dialogs in the same way that JOptionPane does in Java.

The only real difference here is how the events are set up, and the name of the components used. The following table lists the C# equivalents of the ones we have made use of in the course of this book:

Table of C# and Swing GUI Objects
Fig 34.2: Table of C# and Swing GUI Objects

34.5

Hooray for Arrays (in C#)

Arrays in C# work very similarly to those in Java, except that the syntax is a little stricter. Java allows the array brackets to go on either the variable type or the variable name, whereas C# requires it to be on the variable type:

Valid Array Syntax
Fig 34.3: Valid Array Syntax

Other than that, for single dimensional arrays the syntax is identical. Things get a little different when dealing with multidimensional arrays. A two dimensional array of 100 elements by 100 elements is declared as follows in C#:

int[, ] bing = new int [100, 100]; 

The number of dimensions in an array is indicated by commas within a single square bracket notation, and accessing individual elements is done likewise:

using System; 

public class ArrayExample {

public static void Main (String[] args) {
int[, ] bing = new int [100, 100];
int tmp;
bing[10, 10] = 100;
tmp = bing [10, 10];
Console.WriteLine (tmp);
}

}

And the same structure repeats for further orders of dimensionality. For example, a three dimensional array:

using System; 

public class ArrayExample {

public static void Main (String[] args) {
int[, , ] bing = new int [100, 100, 100];
int tmp;
bing[10, 10, 10] = 100;
tmp = bing [10, 10, 10];
Console.WriteLine (tmp);
}

}

C# provides us with an ArrayList class that works very similarly to our Java ArrayList - it resides in a package (sorry, namespace) called System.Collections - so we must import (sorry, indicate that we are using) that pack... namespace, before we can make use of it.

The only difference is in the way we access elements of an ArrayList object - we add elements using an add method as usual, but we use standard array notation (square brackets) to reference specific elements:

using System; 
using System.Collections;

public class ArrayListExample {

public static void Main (String[] args) {
ArrayList myList = new ArrayList();
String tmp;
myList.Add ("Bing!");
myList.Add ("Bong!");
tmp = (string) myList[0];
Console.Out.WriteLine (tmp);
}

}

34.6

Strings in C#

Again, there are more similarities than differences in the way C# deals with strings. Strings are immutable, and so append operations are very costly. Where Java provides a StringBuffer class to deal with this, C# provides a StringBuilder class located in the System.Text namespace.

As with the ArrayList, C# uses the array index syntax to access individual characters in a string - this is in place of the charAt method:

using System; 

public class StringExample {

public static void Main (String[] args) {
String bing = "Bing!";
char tmp = bing[0];
Console.WriteLine (tmp);
}

}

C# offers no StringTokenizer class for parsing Strings, but it does provide a Split method to break strings into multiple tokens. This method is not as powerful as the Java method because it provides no regular expression support, but it is sufficient for most requirements:

class TokenizationExample { 
static void Main (string[] args) {
String str = "Bing, Bong";
String[] tokens = str.Split (', ');
foreach (String t in tokens) {
Console.Out.WriteLine ("" + t);
}

}

}

There is also a Replace method for C# strings, but it too provides no regular expression support. Otherwise it works identically to the replaceAll method of Java's Strings.

34.7

Objects in C#

The relationship between objects in Java and objects in C# is (surprisingly) very similar - they both use the same access modifiers (although with different names in some cases), although C# provides an additional two modifiers.

The table belong shows the mapping of C# access modifiers to Java modifiers:

Access Modifiers in C#
Fig 34.4: Access Modifiers in C#

The main difference with class syntax is in the syntax required to indicate an inheritance, and the syntax required to indicate an implementation:

public class myExample : 

As mentioned above, a colon takes the place of the extends keyword. Additionally, a comma takes the place of the implements keyword.

Constructor methods in C# follow the exact same syntax as in Java - the name of the class with no return type. However, C# also provides a destructor method syntax which contains code to be executed when the object is destroyed (the subtleties of this are beyond the scope of this chapter). The destructor method has the same syntax as a constructor method except that the method name begins with a tilde (~):


public ~myExample() {
Console.WriteLine ("Help me, I'm drowning!");
}

There is one more significant difference in object handling in C# and that is with the way accessor methods are handled. C# provides a new format for writing these, and it is known as the property. Rather than write a set and get method for each private variable, we create a property scheme that allows us to externally access the variable as if it were public access (for example, the way we accessed the text property of the button above), but still gain the benefits of controlling the way they are manipulated.

Consider the following property definition in a larger class:


private int myVariablepublic int MyVariableProperty {
get {
return myVariable;
}

set {
myVariable = value;
}

}

With this definition, we can access the myVariable attribute through the MyVariableProperty property:

myClass bing = new myClass(); 
bing.MyVariableProperty = 100;

value is a special keyword in C# indicating whatever the user passes to the property as the right hand side of an equals operation.

MessageBox.show ("The value of myVariable is " + bing.MyVariableProperty + "!", 
"Properties!");

34.8

Exceptions in C#

C# follows the exception model of error handling - and uses try, catch and finally in ways that mirror that of the Java syntax. All exceptions in C# are likewise derived from a class called Exception, and we can make use of polymorphism to group exceptions by family for easy generalisation of error functionality.

C# offers no mandatory acknowledgement exceptions, which means that there is no code that you must try and catch before you can compile the program. Whether this is a good or bad thing is up for debate.

class ExceptionExample { 
static void Main (string[] args) {
int numOne = 10;
int numTwo = 0;
int answer;
try {
answer = numOne / numTwo;
}

catch (Exception ex) {
Console.Out.WriteLine (ex.Message);
}

}

}

34.9

File I/O in C#

C# provides stream based file IO for disk operations... these classes reside in a namespace called System.IO. We use the FileStream class to initiate a connection with a file:

FileStream input = new FileStream ("myfile.txt", FileMode.Open); 

We use this for both reading and writing, then wrap this using either a StreamReader or StreamWriter as appropriate:

StreamReader in = new StreamReader (input); 

We use the ReadLine method to read information from a StreamReader, and the Write method to write strings to a StreamWriter:

String str = in.ReadLine(); 
while (str != null) {
Console.WriteLine (str);
Str = in.ReadLine();
}

There is another difference in that C# won't automatically create a file if none exists - you must specify that you wish to do so through the use of the second parameter that is passed to the FileStream constructor:

File Modes
Fig 34.5: File Modes

34.10

Sound and Vision in C#

Images in C# are dealt with using an Image class. The Image class specifies a method called FromFile that returns an Image object from a specified filename:

Image myImage = Image.FromFile ("Bing.gif"); 

We can then make use of this image in a PictureBox component, or by using the onPaint method of an application (this is the C# version of the Java paint method):


public void OnPaint (PaintEventArgs pe) {
Graphics g = pe.Graphics;
g.drawImage (myImage, 50, 50, 200, 200);
}

Does this look familiar? It should - aside from the fact that C# treats painting as an event that comes with its own paint arguments, it works exactly the same way, even down to the first five parameters of drawImage!

At the time of writing, the .NET framework offers no support for sounds (ludicrious? Maybe!). There are mechanisms that can be used to play sounds, but they involve accessing DLL files and so are outside this basic comparison of the two languages.

34.11

HashMaps

Hashmaps are present and correct in C#, except that the class is called Hashtable (available in the System.Collections namespace):

Hashtable myHash = new Hashtable(); 

We put a key/value pair into the Hashtable using the add method:

myHash.add ("Bing", "Bong"); 

And again, we use the array access syntax to access individual values - except that instead of passing an integer value, we pass an object:

String str = myHash["Bing"]; 
myHash["Bing"] = "Bang!";

Aside from these changes, we can use Hashtables in exactly the same way we can use HashMaps in Java.

34.12

Abstract Classes and Polymorphism

C# provides indentical syntax to Java for defining interfaces:


public interface myInterface {
void doSomething();
int returnSomething();
}

And likewise identical syntax for declaring abstract classes:

abstract class myAbstractClass { 
// Code goes here
}

And abstract methods:

abstract class myAbstractClass { 
abstract public void myAbstractMethod();
}

Polymorphism is present and correct in C# just as it is in Java, so these object modelling techniques are just as useful.

34.13

Mouse Events

We can handle mouse events in C# in a similar way to how we handle other events. We define what event we want to deal with, and then create a handler object that indicates where the method to deal with it may be found. In the case of a mouse event, we create a MouseEventHandler (found in System.Windows.Forms):

this.MouseDown += new MouseEventHandler (MousePressed); 

Once we've registered a listener, we then provide a handler method (in this case, one called MousePressed):


public void MousePressed (object ob, MouseEventArgs e) {
MessageBox.Show ("Bing", "Bing");
}

We can catch mouse move events in exactly the same way:

this.MouseMove += new MouseEventHandler (MouseMoved); 

And:


public void MouseMoved (object ob, MouseEventArgs e) {
MessageBox.Show ("Bing", "Bong");
}

The MouseEventArgs object passed into the method contains properties for accessing X and Y co-ordinates just like the MouseEvent object in Java does.

34.14

Key Events in C#

We can handle Key Events in a very similar way:

this.KeyPress += new KeyPressEventHandler (KeyPressed); 

And:


public void KeyPressed (object ob, KeyPressEventArgs e) {
MessageBox.Show ("" + e.KeyChar);
}

As you can see, the event handling model for C# is slightly different, but not so different that it makes things difficult to infer. In many ways, it is simpler to set up an event handling object in C# because there is no need to implement the corresponding interface - just provide a suitable method that handles the code.

34.15

And now, to put it all to the test!

We'll put all of this new found syntax into practise and return to our drawing package case study - that involved quite a lot of complexity over a range of areas. We'll demonstrate our familiarity with C# by translating this case study from Java!

We're going to simulate the interface of our Java application, so we need to look a little at how we can do this in C#. Surprisingly, C# doesn't follow a layout manager model that we can make use of, so we need to provide fixed co-ordinates for each of the components. We will make use of the fixed co-ordinate positioning we saw in our chapter on C#:

using System; 
using System.Windows.Forms;
using System.Drawing;
class DrawingPackage :
Form {
public Button setColour;
public ComboBox chooseShape;
public HScrollBar chooseLength;
public VScrollBar chooseHeight;

public static void Main (String[] args) {
Application.Run (new DrawingPackage());
}


public DrawingPackage() {
this.Size = new Size (500, 500);
setColour = new Button();
setColour.Text = "Choose Colour";
setColour.Location = new Point (10, 10);
setColour.Size = new Size (150, 20);
chooseShape = new ComboBox();
chooseShape.Size = new Size (300, 35);
chooseShape.Location = new Point (180, 10);
chooseLength = new HScrollBar();
chooseLength.Size = new Size (480, 20);
chooseLength.Location = new Point (10, 450);
chooseLength.Minimum = 1;
chooseLength.Maximum = 50;
chooseLength.Value = 10;
chooseHeight = new VScrollBar();
chooseHeight.Size = new Size (20, 400);
chooseHeight.Location = new Point (470, 40);
chooseHeight.Minimum = 1;
chooseHeight.Maximum = 50;
chooseHeight.Value = 10;
this.Controls.Add (setColour);
this.Controls.Add (chooseShape);
this.Controls.Add (chooseLength);
this.Controls.Add (chooseHeight);
}

}

The fact that we don't have standard layout managers brings us back to the same problem we had with setBounds in Java - we won't look at how to resolve this since it involves some fairly tricky calculations that would distract us from the main purpose of the chapter.

Using a standard builder interface (like Visual Studio .NET) makes this task a lot easier than we've seen using JCreator - this isn't a feature of C#, but simply a consequence of the environment being used. There are equivalent environments for Java (such as JBuilder, or Sun's Forte) that allow interfaces to be developed using drag and drop.

We can compile and execute the application above, and see our first C# interface. It's not identical to our Java interface since we don't have the layout managers to regulate distribution of components. It's functional enough however and we can worry about prettying it up later should the need arise. For our purposes, we're far more interested in the code that lies underneath the surface, so we can leave this interface as it is and concentrate on the Good Stuff.

Application Screenshot
Fig 34.6: Application Screenshot

34.16

Shapes

We're going to follow exactly the same development process for this application as we did for the Java version, so we're going to make use of a class called Shape to provide definition to all the children classes. This class will perform exactly the same role, include the same functionality and have exactly the same methods. The only difference is that we won't be providing accessor methods - instead we'll make use of the property structure to provide access to our variables:

using System; 

public class Shape {
private int x;

public int X {
get {
return x;
}

set {
x = value;
}

}

private int y;

public int Y {
get {
return y;
}

set {
y = value;
}

}

private int length;

public int Length {
get {
return length;
}

set {
length = value;
}

}

private int height;

public int Height {
get {
return height;
}

set {
height = value;
}

}


public Shape (int nx, int ny, int nlen, int nht) {
x = nx;
y = ny;
len = nlen;
ht = nht;
}

}

As you can see, the code is very similar except that all of our accessor methods have been condensed down into more compact property statements. This syntactical nicety is elegant, but offers nothing significantly new over what Java provides.

Now that we have our Shape class, we can start extending it into specific shapes. We don't need to actually provide a constructor for these, but we're going to anyway as a way to demonstrate another syntactical difference with C#. There is no call to super in the constructor method - instead, the reference to the parent constructor method is made in the method declaration:

Public Circle() : base()

A strange design decision, but let's not allow it to trouble us.

Another difference is in how we handle the drawing portion of the functionality. We still use a Graphics object, which has a method called drawEllipse which will draw a circle, and fillEllipse which will draw a filled Circle. However, in an unusual move the developers of C# have determined that these should have a pen/brush object passed as their first parameter.

Empty outlines (using the DrawX methods) require a pen, filled outlines (using the FillX methods) require a brush. We're going to be drawing a filled circle, so we need to create an instance of a class called SolidBrush:

using System; 
using System.Drawing;
public class Circle :
Shape {
public Circle (int x, int y, int len, int ht) :
base (x, y, len, ht) {
}


public void drawShape (Graphics g) {
SolidBrush redBrush = new SolidBrush (Color.Red);
g.FillEllipse (redBrush, X, Y, Length, Height);
}

}

Aside from this, it works the same way as before. The following table maps Java drawing methods onto C# drawing methods:

C# Drawing Methods
Fig 34.7: C# Drawing Methods

We can use this same structure to implement our Rectangle shape also:

using System; 
using System.Drawing;
public class Rectangle :
Shape {
public Rectangle (int x, int y, int len, int ht) :
base (x, y, len, ht) {
}


public void drawShape (Graphics g) {
SolidBrush redBrush = new SolidBrush (Color.Red);
g.FillRectangle (redBrush, X, Y, Length, Height);
}

}

As you can see, although the syntax is a little different (perhaps largely because the C# developers wanted to distance themselves as much as possible from claims that C# is a simple copy of Java), the structure is very much the same as with the classes we wrote for Java. This is true for almost everything we'll do in C#.

34.17

The Model

Now to implement the model that sits between our application and our classes. C# provides us with an ArrayList class, so this is a direct mapping from what we have in Java to what we need in C#. Notice here though that we are using the new foreach notation to implement the drawAllShapes method. We could just as easily do this with a normal for loop, but hey - when in Rome!

using System; 
using System.Collections;
using System.Drawing;

public class Model {
ArrayList shapesToDraw;

public Model() {
shapesToDraw = new ArrayList();
}


public void addShape (Shape s) {
shapesToDraw.Add (s);
}


public void drawAllShapes (Graphics g) {
foreach (Shape s in shapesToDraw) {
s.drawShape (g);
}

}

}

Now we reach the same problem in C# as we did in Java - it won't compile until we turn our Shape class into an abstract class with a corresponding abstract method for drawShape. So that's exactly what we're going to do. The syntax for this is identical to the syntax for Java.

However, there is a slight difference - in this case, it still won't compile, and it will refuse to compile until we add an override keyword to the method definitions for drawShape in both Circle and Rectangle. This specifies to C# that we're providing our own implementation and not making use of the base one (which we can't anyway, because it is abstract):

using System; 
using System.Drawing;
public class Rectangle :
Shape {
public Rectangle (int x, int y, int len, int ht) :
base (x, y, len, ht) {
}


public override void drawShape (Graphics g) {
SolidBrush redBrush = new SolidBrush (Color.Red);
g.FillRectangle (redBrush, X, Y, Length, Height);
}

}

Now it will compile happily (or at least, happily enough). This syntax seems particularly strange considering the clean implementation of this as provided in Java - the extra complexity of having to specify an over-ridden method seems as if it adds additional syntax for no compelling reason. Ah well... at least we're learning more as we go along!

34.18

Adding the Mouse Events

We looked at this briefly in the chapter on C# - we don't need to go to the trouble of implementing any listener objects, instead we register a separate handler method for every event we're interested in. At the moment, we're only going to be interested in mouse click events.

Before we get to that part, we need to add our utility method to the model that allows us to list all the valid shapes:


public ArrayList listValidShapes() {
ArrayList tmp = new ArrayList();
tmp.Add ("Circle");
tmp.Add ("Rectangle");
return tmp;
}

And then we populate the ComboBox in our application interface with all the relevant shapes. We need to access the Add method of the Items property of the ComboBox to do this, there is no method of ComboBox that directly allows us to do this:

...public Model handler; 
public DrawingPackage() {
handler = new Model();
...
tmp = handler.listValidShapes();
foreach (string s in tmp) {
chooseShape.Items.Add (s);
}

chooseShape.SelectedIndex = 0;
}

But having done that, our ComboBox now has all the valid shapes listed, just like with our Java application. Now we just need to be able to draw things!

We need to add an event handler for a mouse click event - we saw how to do this earlier in this section:

this.MouseDown += new MouseEventHandler (MousePressed); 

We add this into the constructor method, and then we provide a handler method. Before we do that, we need another method in our model - our createShape method:

public void createShape (String shape, int x, int y, int len, int ht) 
{
Shape temp = null;
if (shape.Equals ("Circle")) {
temp = new Circle (x, y, len, ht);
}

else if (shape.Equals ("Rectangle")) {
temp = new Rectangle (x, y, len, ht);
}

addShape (temp);
}

And then we add our mouse event handler:


public void MousePressed (object ob, MouseEventArgs e) {
handler.createShape (chooseShape.Text, e.X, e.Y, chooseLength.Value, chooseHeight.Value);
}

And then we need to implement the corresponding paint method (called OnPaint in C#). Note that we require another override modifier in the method declaration:


protected override void OnPaint (PaintEventArgs e) {
base.OnPaint (e);
Graphics g = e.Graphics;
handler.drawAllShapes (g);
}

And then we require something that will call this method whenever we draw a shape - we need to add another line to our mouse handler:


public void MousePressed (object ob, MouseEventArgs e) {
handler.createShape (chooseShape.Text, e.X, e.Y, chooseLength.Value, chooseHeight.Value);
this.Refresh();
}

And then when we run our application, we can now draw shapes all over the screen just like with our Java application:

Drawing Shapes
Fig 34.8: Drawing Shapes

However, we're missing the functionality required to allow the user to choose different colours for their shapes. That's our next task.

34.19

Multicolour

As with our Java application, we need to alter our Shape abstract class to provide methods for setting and getting the colour. We'll do this with another property:

private Color myColour; 

public Color Colour {
get {
return myColour;
}

set {
myColour = value;
}

}

And then we need to replace our placeholder colour choice of red with whatever colour the user selects. For example, with our Rectangle:


public override void drawShape (Graphics g) {
SolidBrush Brush = new SolidBrush (this.Colour);
g.FillRectangle (Brush, X, Y, Length, Height);
}

Now we need to provide the user with a way to select the colour - we do this through a ColorDialog in C#. First we need to add an event handler to the relevant button (we do this in the constructor):

this.setColour.Click += new EventHandler (SetDrawingColour); 

And then we provide the method that invokes the ColorDialog and sets the drawing colour appropriately:


public void SetDrawingColour (object ob, EventArgs e) {
ColorDialog myColor = new ColorDialog();
myColor.ShowDialog();
DrawingColour = myColor.Color;
}

And then we modify our createShape method in the Model class to take a new parameter, that of the drawing colour:


public void MousePressed (object ob, MouseEventArgs e) {
handler.createShape (DrawingColour, chooseShape.Text, e.X, e.Y, chooseLength.Value
, chooseHeight.Value);
this.Refresh();
}

And there we go, our Java application written entirely in C#:

Finished Application
Fig 34.9: Finished Application

34.20

Ta-da!

And that's all it takes - even a fairly sophisticated application like this can be built using little more than our existing Java knowledge and a reference book on C# - the only difference is in the syntax since the model used by Java and C# regarding class structures and event handling is almost identical.

It will still take some practise before you are as fluent in C# as you are in Java - but it's not going to take as long to learn this language as it took to learn Java. From now on, new languages will become easier and easier to pick up because you now have a solid base of reference from which to work.

As you continue on with both languages, you will find things that you like in one that you don't like in the other, and vice versa. Each language has its strengths and weaknesses, and as a developer it is necessary to adapt to changing requirements and use different languages to accomplish different tasks.

As has been mentioned previously, the most important part of being a programmer is the mindset that allows you to approach problems and develop solutions. Knowing a particular language is a secondary concern, since provided you are willing to put in a week or so to learn the syntax, you can drift between different environments like a true programming polyglot, as hopefully this case study will have demonstrated.

34.21

Conclusion

Although we have spent most of the time in this book looking at what it's possible to do in Java, those skills that we have picked up are not limited to just that one programming language. The most difficult thing in programming in any language is just learning how to think how best to express the problem in terms the computer will understand - the actual language we use is largely irrelevant to that.

Learning different programming languages is not an insurmountable task once we've reached a certain level of development as programmers - it's not like learning French and then trying to learn Japanese. Instead, it's like learning English and then trying to learn the slang expressions of certain English locales. There is an underlying structure to programming that is communicated beyond the simple syntax.

We have taken the hard route through Java for this book - there are many development environments out there that make building user interfaces much simpler than the 'bare bones' approach we've taken. We've gone the hard route because the level of knowledge we attain as developers who have learned how to build applications (rather than write them) is inevitably shallower and less transferable.

However, here's the good news - now that you know what is going on when you create a JButton component in JBuilder, there's nothing to stop you actually making use of it to automate most of your GUI development, leaving you free to concentrate on the difficult, rather than routine, parts of development.

Likewise with C# - very rarely do people develop large C# applications using only a text editor. Most of the time, it is done in a powerful and versatile development environment like Visual Studio .NET. But now that you know what's going on underneath, you'll have a greater appreciation of the way the language works and what can be done if the IDE fails to deliver the fine-tuning you require.

Although reading through this chapter doesn't mean you're fluent in C#, it does mean that you're familiar enough with it to start really practising - you never learn how to use a programming language until you've written something fairly substantial in it.

You're well enough equipped that you can write an application that will really tax your skills, and in doing so really underline the ways in which C# is the same as Java, and the ways in which it is different. Give it a week, and you'll be a competent C# programmer too!

Further Reading

The following table details further reading on the topic in this chapter, and also any external resources that you may find useful.

ResourceDescription
Example Programs from this chapterThis is a zip file of all the programs shown in this chapter. Requires the .NET Framework to run.

PreviousTable of ContentsNext

© 2004-2006 Michael James Heron