Transitioning between Java and C#

Table of Contents

Introduction

One of the challenges new programmers face is in making that initial leap between their first and second language. This unit is intended for those who already have experience programming and are transitioning between Java and C# (in either direction). Fortunately, both of these languages are imperative, so much of the structure and execution of the programs will seem familiar. Also, just as Java borrowed much of its syntax from C and C++ and included additional features, C# borrowed concepts from Java and incorporated its own feature set. It is hoped that after reading through this unit, you will begin to understand that just about any language you work in will have variables, conditionals, functions (or methods), the ability to perform I/O, and so on. In other words, to learn a new imperative language, you don’t have to learn how to program (again), you just need to review the syntax. That being said, transitioning into a functional or declarative languages (like LISP or Prolog) is a much different beast since it requires a different way of thinking.

 This unit is organized such that students who are in a time crunch can quickly get the gist of things by viewing code (“Show me the code already!”) as well as one of the two summaries at the end of each section. Those with a little more time on their hands can go into more detail by reading the accompanying text. This unit also serves as a compilation of sorts because it links to several other resources which are quite handy and should be read – again, if you have the time. To facilitate understanding, the code appears side-by-side, with Java on the left and C# on the right. In cases where one language supports a feature set and the other does not, only one column appears. It should also be noted that some liberties were taken in the code - such as including java.lang.* in the Java examples and System in the C# examples. This code should clearly identify which language each example is in without an explicit "This is C#" or "This is Java" heading.  Finally, the writing is purposely terse and informal in hopes that it will be more enjoyable to read and get you up to speed as quickly as possible.

Beginnings

Skeleton code:

Traditionally, programmers start with a minimalistic program called Hello World, which, as its name implies, usually prints “Hello World” to the screen or console. An example of this program is presented below in both languages. Realize that if you are using an IDE to auto-generate this code, it may vary slightly (e.g. importing or using additional libraries).

import java.lang.*;


class HelloWorld 
{
	public static void main (String[] args) 
	{
		// Print Hello World
		System.out.println ("Hello, World!");
	} // main
} // class
using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
        	// Print Hello World
        	Console.WriteLine("Hello, World!");
        } // Main
    } // class
} // namespace

When looking at these sections of code side by side, you can see that the languages are similar in structure and syntax. First, both languages are case-sensitive. The keywords import and using are essentially the same - eliminating the need to specify the namespace or package before declaring and instantiating variables (and should not truly be considered part of the skeletal code). System.out.println() performs the same function as Console.WriteLine() (and have equivalent System.out.print() and Console.Write() methods that do not insert a newline).  Semicolons, parentheses, curly braces, brackets and so on appear in the same manner (and generally denote the same things). Commenting is the same and supports both single line comments (//) as well as paragraph commenting (/* and */). As expected, the word main represents the entry point into the program and because both languages are object-oriented, main appears inside a class definition.

When looking closer, however, there are some subtle difference that should be discussed. First, note that Main is capitalized in C#. This is because convention states that methods are capitalized in C#, and given that main is a method, this makes sense. The convention for both languages dictate that methods comprised of multiple words should capitalize the first letter of each word; however in Java, the first letter of a method should be lower-case.

The second thing to note is that string is lower-case in C# yet upper-case in Java. This is because string is a reserved word in C# and serves as one of the primitive data types. In Java, String is a complex data type. Data types will be reviewed in the next section.

If you are new to C#, you probably noticed the reserved word namespace in the example. This is nothing to be afraid of. Namespaces are a way of grouping related classes together. The name of the namespace is auto-generated when the project is initially created in Visual Studio.

Even more subtle, - realize that the code should be placed into a file called HelloWorld.java. If HelloWorld was declared as a public class, this would be required.

Keywords

Though it is beyond the scope of this unit, it is worthwhile to further demonstrate the similarities of Java and C# via their keywords (or reserved words). Below is a side-by-side comparison between the keywords in C# and Java - comparing them semantically. For example, even though both languages have a protected keyword, there is a semantic difference. Because there are significantly more reserved words in C#, the list below is categorized alphabetically. Note that some keywords (such as final in Java) are context-sensitive - appearing before class definitions, methods and variables, and therefore may appear more than once in the list.

C#Java
abstract abstract
as-
base super
bool boolean
break break
byte-
case case
catch catch
char char
checked-
class class
C#Java
const final
continue continue
decimal-
default default
delegate-
do do
double double
else else
enum-
event-
explicit-
C#Java
extern native
false false
finally finally
fixed -
float float
for for
foreach -
get -
goto goto
if if
implicit -
C#Java
in(:)
int int
interface interface
internal protected
is instanceof
lock synchronized
long long
namespace package
new new
null null
object-
C#Java
operator-
out-
override-
params(...)
partial-
private private
protected (protected)
public public
readonly-
ref-
return return
C#Java
sbyte byte
sealed final
set-
short short
sizeof-
stackalloc-
static static
string-
struct-
switch switch
this this
C#Java
throw throw
true true
try try
typeof-
uint-
ulong-
unchecked-
unsafe-
ushort-
using import
value-
C#Java
virtual (abstract)
void void
volatile volatile
where extends
while while
yield-
: extends
: implements
-strictfp
-throws
-transient

 

Primitive Data Types and Variable Declaration:

Declaring variables in either language is similar and follows this format:

<data type> <variable name>;

Most languages include support for a wide variety of numbers, characters, and Booleans. They may also include strings and other data types. In general, a number can be categorized as being either a whole number or a floating point number, and be either signed (positive or negative) or unsigned (positive only). The precision of the number is governed by the number of bits used to represent it. Fortunately, both C# and Java rely on a virtual machine, so the number of bits used for each data type is consistent across platforms. Below is a list of primitive data types for each language:

Java C#
boolean - 1 bit. Can only be assigned true or false.
byte - 1 byte (in 2's complement). Range -128 to +127.
short - 2 bytes (in 2's complement). Range -32,768 to +32,767.
int - 4 bytes (in 2's complement). Range -2,147,483,648 to +2,147,483,647.
long - 8 bytes (in 2's complement). Range -9.223e-18 to +9.223e+18 (approximately).
float - 4 bytes (IEEE 754). Range 1.401e-45 to +3.402e+38 (approximately). Can be positive or negative
double - 8 bytes (IEEE 754). Range 4.94e-324 to +1.797e+308 (approximately). Can be positive or negative
char - 2 bytes (Unicode, unsigned). Range 0 to 65,535
bool - 8 bits
byte and sbyte - 1 byte each. Range is 0 to 255 and -128 to + 127, respectively
short and ushort - 2 bytes each. Range is -32,768 to +32,767 and 0 to 65,535, respectively
int and uint - 2 bytes each. Range is -2,147,483,648 to +2,147,483,647 and 0 to 4,294,967,295, respectively
long and ulong - 2 bytes each. Range is -9.223e-18 to +9.223e+18 and 0 to 18,446,744,073,709,551,615, respectively
float - 4 bytes. Range -3.402e38 to +3.402e+38 (approximately).
double - 8 bytes. Range -1.797e308 to +1.797e+308 (approximately).
char - 2 bytes (Unicode, unsigned). Range 0 to 65,535

Note to those learning C#: There are several additional built-in data types in C#, such as object, string, and decimal (which has a range of ±1.0 × 10e−28 to ±7.9 × 10e28).  Further, each primitive data type has an equivalent .NET class associated with it: bool has Boolean, byte has Byte, sbyte has SByte, short has Int16, ushort has UInt16, int has Int32, uint has UInt32, long has UInt64, float has Single, double has Double, and so on.  The process of converting between a primitive and its associated class is called boxing, which in Java, requires the programmer to do manually. Below is an example of automatic boxing:


// Example of boxing and unboxing in C# 
int primitive = 42;
// Box it up automatically
object boxed = primitive;
// Unbox it using a type case
int unboxed = (int)boxed; 

You may be both curious and surprised to as to why there are so many additional data types in C#.  It turns out that one of the original creators of Java (Gosling) didn't really see the need to include unsigned data types (excluding char) because he felt that they complicated the language.

Constants:

Java and C# both enable a developer to declare a variable as constant (i.e. the variables value cannot be changed at runtime). To create a constant in Java, add the keyword final before the variable declaration. In C#, add the const keyword. For those who are new to C#, realize that there is also the option of declaring a variable to be readonly. This modifier allows a variable to be assigned exactly once during runtime - unlike const which requires initialization at the time the variable is declared.

 

C# to Java Summary:

Java to C# Summary:

 

Conditionals and Repetition

Conditionals

It should come as no surprise to you that C# and Java contain if and else keywords; without these, what kind of language would it be? However, the behavior of switch statements is different. First, C# allows switch statements to use strings as opposed to numeric data (which can be quite convenient). Second, C# disallows fall-throughs unless the case statement contains no code.  A fall-through occurs when a case matches and then continues on to the next case statement until a break statement is reached; thus, the intent is to "fall down" to the next case. If you're unfamiliar with switch statements (or it has been a while), recall that when a case statement matches the value of the variable that is being compared, it will continue processing line by line until reaching a break statement. The example below demonstrates this.

import java.lang.*;


class NowThatsOdd 
{
	public static void main (String[] args) 
	{
	    for (int i = 6; i >= 1; i--)
            {
                switch (i)
                {
                    case 6:
                    case 4:
                    case 2: System.out.println(i + " is even");
                        break;
                    case 5:
                    case 3:
                    case 1: System.out.println(i + " is odd");
                        break;
                } // switch
            } // for
	} // main
} // class
using System;

namespace NowThatsOdd
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 6; i >= 1; i--)
            {
                switch (i)
                {
                    case 6: 
                    case 4: 
                    case 2: Console.WriteLine(i + " is even");
                        break;
                    case 5:
                    case 3:
                    case 1: Console.WriteLine(i + " is odd");
                        break;
                } // switch
            } // for
    	} // Main
    } // class
} // namespace

With both of these programs, the output is the same:

6 is even
5 is odd
4 is even
3 is odd
2 is even
1 is odd

For Java programmers, disallowing fall-throughs may seem restrictive. However, this was apparently enforced in C# because of the number of bugs generated from such code as well as the difficulty in tracking them down.

For C# programmers, you should be aware that Java allows fall-throughs that can execute code per case statement. The example below (in Java) demonstrates the behavior. It may not be exactly what one would expect...

import java.lang.*;

class BeCareful {
        public static void main (String[] args) {
            for (int i = 5; i >= 1; i--)
            {
                switch (i)
                {
                    case 5: System.out.print (i + " "); 
                    case 4: System.out.print (i + " ");
                    case 3: System.out.print (i + " ");
                        break;
                    case 2:
                    case 1: System.out.print (i + " ");
                }
                System.out.println (" ");
            }
        }
}

The output of this code is:

5 5 5
4 4
3
2
1

Note that, in this case, a break statement was not needed after case 1 because Java allows non-empty fall-throughs.

 

Repetition

Repetition in both Java and C# is nearly identical. Both languages support for, while and do-while constructs and because of this, they won't be covered here. It is also true for both languages that loops can be "abused" to a certain extent - such as what is allowable in C/C++. However, C# includes an explicit foreach loop - which is a concise approach to iterating through collections. This behaves similarly to the (lesser-known) ':' operator in Java (for data structures implementing the java.lang.Iterable interface). In the example below, we create an array of four strings called myArray and iterate through it - printing each string on its own line.

import java.lang.*;


class IterationExample 
{
	public static void main (String[] args) 
	{
		// Create an array of Strings
		String[] myArray = {"This", "is", "a", "test"};

		// Iterate through the array
		for (String s : myArray) {
			System.out.println (s);
		} // for
	} // main
} // class
using System;

namespace IterationExample
{
    class Program
    {
        static void Main(string[] args)
        {
        	// Create an array of strings
        	string[] myArray = {"This", "is", "a", "test"};
		// Iterate through the array
		foreach (string s in myArray) {
			Console.WriteLine (s);
		} // foreach
        } // Main
    } // class
} // namespace

The loop execute four times - one for each string in myArray. During each pass, the variable s is updated to point to each successive string in the array. The output for these programs will therefore be:

This
is
a
test

C# to Java Summary:

Java to C# Summary:

 

Methods

To begin, it is important to get our terminology straight. When reading through literature, you may see terms such as subroutine, procedure, function, methods or behavior. For all practical purposes, these are the same thing (though computer scientists specializing in languages would strongly disagree - perhaps turning red in the face at such a suggestion). The justification for such a statement is that all of these "things" generally provide us with a level of abstraction - allowing us to neatly package related code together into a logical unit that we can repeatedly call. The terminology changed semantically with the introduction of Object-Oriented Programming (OOP), because functions now resided inside a class and represented things that instances of the class (called objects) could "do". 

Fortunately, declaring methods in both C# and Java follow the standard C-like template:

<return type> <method name> (<parameters>) 
{
	<method body>
}

In Java, it is convention to begin method names with a lower-case letter. In C#, method names begin with an upper-case letter. For both languages, however, convention dictates that each successive word in a method name should be capitalized. For example, the prototype of a method may look like the following:

myMethodName( ); // Java
MyMethodName( ); // C#

Both languages also allow for any number of modifiers to appear before the return type, such as keywords public, private, static and so on. Calling methods that are not declared static follows a template as well:

<object>.<method>(<arguments);

Realize that because both languages are object-oriented, neither of them supports traditional stand-alone methods (also called global methods) like those found in C. It's still possible, however, to simulate them. Methods must:

  1. Reside inside a class and
  2. Be declared static

This also changes the way that the method is called (since it is not necessary to create an object to call the method). The method would therefore be invoked by referring to the class name:

<Class>.<method>(<arguments);

 

A Preface to Parameter Passing: Variable Types

Parameter passing has caused much confusion over the years, so hopefully this will help clarify things. Part of the problem is with terminology...

First, variables can be created as a reference type or a value type. As its name suggests, a reference type creates a reference to where the data resides in memory (as shown Figure 1 below). When working with classes (and not structs in C#), you create instances called objects. These objects are actually references to where the actual data resides. For example, imagine that we have defined a class called Dog that has three attributes: a weight, a name, and whether or not it is rabid. Then, we could declare two objects (that are references) and modify the weight:

Dog d1 = new Dog();
d1.weight = 10;
Dog d2 = d1;
d1.weight = 20;
System.out.println (d2.weight);
Dog d1 = new Dog();
d1.weight = 10;
Dog d2 = d1;
d1.weight = 20;
Console.WriteLine (d2.weight);

Output: 20


In line 1, we have created a reference to a new Dog (called d1) and in line 2 have set its weight to 20. In other words, line 1 allocated a chunk of memory and had d1 point to it. In line 2, we follow d1 to the actual weight data and initialize it to the value 10.  In line 3, we created a second reference (called d2) and have it refer to the same chunk of memory as d1; notice that we didn't allocate another chunk of memory for d2. So at this point, memory looks something like this:

Figure 1: References to memory

In line 4, we set the weight of d1 to be 20. This explains why the output of the code snippet above is 20 when we print out d2's weight: both d1 and d2 are referring to the same chunk of memory and changing one changes the other.

Now that you have a better understand of reference types, value types are very simple to describe. Instead of having references (i.e. a level of indirection) between the variable and where the object resides in memory, each variable represents the actual data; they are independent copies. Thus, changing the weight of d1 will not affect the weight of d2.

Figure 2: Independent copies in memory

Note: in C#, creating instances of structs does not create references (they are stack allocated), but instead, individual copies like in Figure 2.

Parameter Passing

Though there are several ways to pass parameters, they are typically passed either by reference or by value. The terminology here is very similar to the previous section (where variables could be either a reference type or a value type). When an variable is passed by reference, it is possible for the method to modify the value of the parameter and for that modification to affect the variable that was passed from the method call; this is what happens when objects are passed to methods (though this is not necessarily true - and will be explained later). When variables are passed by value, a copy of the variable is made when the method is called. The result is that the method cannot change the value of the variable that was passed when the method was called. Let's see an example.

import java.lang.*;


    class Dog
    {
        public int weight;
        public String name;
        public boolean rabid;
    }

    public class RefExample
    {
        // Passing by value: a copy is made
        static void noChange(int val)
        {
            System.out.println("NoChange value before: " + val);
            val++;
            System.out.println("NoChange value after: " + val);
        }
        // Passing a copy of the reference
        static void change(Dog d)
        {
            d.weight++;
        }
        public static void main(String[] args)
        {
            int x = 10;
            Dog d1 = new Dog();
            d1.weight = 99;

            System.out.println ("X before call: " + x);
            noChange(x);
            System.out.println ("X after call: " + x);

            System.out.println ("Weight before: " + d1.weight);
            change(d1);
            System.out.println ("Weight after: "+d1.weight);
        }
    }

using System;

namespace RefExample
{
    public class Dog
    {
        public int weight;
        public string name;
        public bool rabid;
    }

    class Program
    {
        // Passing by value: a copy is made
        static void NoChange(int val)
        {
            Console.WriteLine("NoChange value before: " + val);
            val++;
            Console.WriteLine("NoChange value after: " + val);
        }
        // Passing a copy of the reference
        static void Change(Dog d)
        {
            d.weight++;
        }
        static void Main(string[] args)
        {
            int x = 10;
            Dog d1 = new Dog();
            d1.weight = 99;
            
            Console.WriteLine("X before call: " + x);
            NoChange(x);
            Console.WriteLine("X after call: " + x);

            Console.WriteLine("Weight before: " + d1.weight);
            Change(d1);
            Console.WriteLine("Weight after: "+d1.weight);
        }
    }
}

Output:

X before call: 10
NoChange value before: 10
NoChange value after: 11
X after call: 10
Weight before: 99
Weight after: 100

In the example above, we create a variable of a primitive type (called x) and a reference variable to an object (called d1). Both of these variables are passed to a (static) method that attempts to change the variable in some way. As shown by the output, a copy of the value of x was made and placed into val (i.e. val and x are independent copies). Thus, changing val did not change x. However, looking at our Dog variable, the data inside d1 was modified by the method. This is because, similar to Figure 1, both the variables d1 and d are referring to the same chunk of memory; in other words, d is a copy of d1, but they both refer to the same thing.

Lesson learned: unless otherwise specified, parameters are passed by value. When passing the variable x, the method NoChange() made a copy of it called val. When we passed the reference variable d1 to Change(), it made copy of d1 (which points to a chunk of memory) called d. Again, refer to Figure 1 and Figure 2 for visualizations of this.

You may be asking yourself: "That's fine, but what if I wanted to have d1 point to some other chunk of memory, or assign it a new dog inside method Change()?"  For example, what if a method set d to null like the example below?

import java.lang.*;


    class Dog
    {
        public int weight;
        public String name;
        public boolean rabid;
    }

    public class RefExample
    {
        // Passing the variable the same way
        static void change(Dog d)
        {
	    // Did we change d1 also?
            d = null;
        }
        public static void main(String[] args)
        {
            Dog d1 = new Dog();
            d1.weight = 99;

            System.out.println ("Weight before: " + d1.weight);
            change(d1);
	    // What will happen here?
            System.out.println ("Weight after: "+d1.weight);
        } // main
    } // class

using System;

namespace RefExample
{
    public class Dog
    {
        public int weight;
        public string name;
        public bool rabid;
    }

    class Program
    {
        // Passing the variable the same way
        static void Change(Dog d)
        {
	    // Did we change d1 also?
            d = null;
        }
        static void Main(string[] args)
        {
            Dog d1 = new Dog();
            d1.weight = 99;
         
            Console.WriteLine("Weight before: " + d1.weight);
            Change(d1);
            // What will happen here?
            Console.WriteLine("Weight after: "+d1.weight);
        } // Main
    } // class
} // namespace

The real question is: what would happen when working with this code? Would it compile? Yes - without a hiccup. Would it crash at the comment "What will happen here"?  Surprisingly, no! But why? Remember that when Change() is called, a variable is created (called d) and made to point to the same thing that d1 is pointing to (very similar to Figure 1). However, while d was originally pointing at the same thing as d1, making d point to null in no way affects what d1 is pointing to. In other words, when d is assigned null, memory looks something like Figure 3.

You may still be asking yourself: "That's fine, but what if I wanted to have d1 point to some other chunk of memory, or assign it a new dog inside method Change()?" Read on...

New in C#: ref and out keywords!

It is quite common to run into situations where a method must be able to change the value that was passed by the one who called it. Unfortunately, this isn't an option in Java; for simplicity, all values are passed by value (even if the variable is a reference type).

However, this is trivially done in C#.  By including the ref keyword - for variables of either type - a method can modify the value of the variable, and that change is seen by the one who called it. Below is an example of code that only works in C#. Note that it is necessary to include the ref keyword in the parameter list as well as when invoking the method.

using System;

namespace Ch_Ch_Ch_Ch_Changes
{
    public class Dog
    {
        public int weight;
        public string name;
        public bool rabid;
    }

    class Program
    {
        // Passing a primitive by reference
        static void ChangePrimitiveType(ref int i)
        {
            i++;
        }
        // Truly passing by reference
        static void ChangeReferenceType(ref Dog d)
        {
            d = null;
        }
        static void Main(string[] args)
        {
            int x = 9;
            Dog d1 = new Dog();
            d1.weight = 99;

            Console.WriteLine("X before call: " + x);
            ChangePrimitiveType(ref x);
            Console.WriteLine("X after call: " + x);

            Console.WriteLine("Weight before: " + d1.weight);
            ChangeReferenceType(ref d1);
            // What happens now?
            Console.WriteLine("Weight after: "+d1.weight);
        }
    }
}

Output:

X before call: 9
X after call: 10
Weight before: 99

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.

So, it looks like it's working! We have one last thing to talk about before moving on, and it is the keyword out. It is not commonly used, but it is very similar in nature to the ref keyword in that parameters marked as out can be modified (the changes are reflected outside the method). However, there's a semantic difference. Marking a parameter as out assumes that the variable will actually be initialized in the method (i.e. the value of the variable at the time it is passed is irrelevant and will not be used).

using System;

namespace AgeProgram
{
    class Program
    {
        
        // A method to initialize a variable
        static void GetUserAge(out int i)
        {   
	    // Warning! Don't use i before it is initialized!
            Console.Write("Enter your age: ");
            i = Int32.Parse(Console.ReadLine());
        }
        static void Main(string[] args)
        {
            int userAge;
            GetUserAge(out userAge);
            // After the method call, userAge has valid data
            Console.WriteLine("Wow! You're " + userAge + " years old!");
        }
    }
}

The output of the program depends on what the user types in as their age, but it performs as expected (printing out "Wow! You're 25 years old!" if the user enters 25). After the method call, the variable userAge has been modified. There are a few things to notice about this example. First (and most obvious) is the inclusion of the out keyword. More subtly is the fact that the return type of the method is still void. You may ask why out is useful at all, considering that we can have non-void return types - and thus we could simply return the value. However, that approach does us no good when we have more than one value that needs to be initialized. Second, note that the variable i was not initialized in Main, and was not used in GetUserAge() before being initialized. In fact, using the variable i before initialization will cause the code not to compile - even if you just try to print out its value!

Could the same example be rewritten using the ref keyword instead? Sure. But using out is a stronger indicator of how the variable is intended to be used.

Variable length parameters using params and ...

As a closing discussion, we'll talk about methods that have a variable number of arguments. This option is sometimes useful when the number of arguments is unknown (or arbitrary), such as a method that can add any number of integers (or floats) together. Both C# and Java support this concept, though the syntax differs. In C#, you must use the params keyword, and it must be used as a modifier to the last parameter (which must be an array). In Java, one must include the string ... between the type and the variable name of the last parameter. Below is an example of a method that takes in a variable number of integers and returns the sum of those numbers.

import java.lang.*;


    public class VariableParameters
    {
        // Takes in a variable number of arguments
        static int addNums (int ... values) {
                int sum = 0;
                for (int i : values) {
                        sum+=i;
                }
                return sum;
        }
        public static void main(String[] args)
        {
                int result = addNums (1, 2, 3, 4, 5, 6, 7, 8);
                System.out.println ("The sum of the numbers 1-8 is: " + result);
        } // main
    } // class

using System;

namespace VariableParameters
{
    class Program
    {
        // Takes in a variable number of arguments
        static int AddNums(params int[] values)
        {
            int sum = 0;
            foreach (int i in values)
            {
                sum += i;
            }
            return sum;
        }
        static void Main(string[] args)
        {
            int result = AddNums(1, 2, 3, 4, 5, 6, 7, 8);
            Console.WriteLine("The sum of the numbers 1-8 is: " + result);
        } // Main
    } // class
} // namespace

 

C# to Java Summary:

Java to C# Summary:

 

Arrays and Collections

Simple arrays

In Java, there are two ways to declare an array: one of them has a similar syntax to C/C++ while the other is a little easier to read (because it adheres to the <data type><variable name> convention) and identical to the way that C# declares arrays. Arrays in both languages are 0-based (for indices/slot numbers) and are static in size (their size cannot change once they have been declared). Similarly, the arrays in both languages are objects; thus, you have the ability to query for the length of the array. The generic templates for declaring arrays are:

Java:
<data type>[] <variable name>;  // OR
<data type> <variable name>[];  // Similar to C++

C#:
<data type>[] <variable name>; 

Below is a code snippet that declares an array of 50 integers, prints out the length of the array, and copies the fifth element into a variable x.

// Declare an array of 50 ints
int[] myArray = new int[50];
// Print out the length
System.out.println (myArray.length);
// Copy the fifth element
int x = myArray[4];
// Declare an array of 50 ints
int[] myArray = new int[50];
// Print out the length
Console.WriteLine (myArray.Length);
// Copy the fifth element
int x = myArray[4];

Multidimensional arrays

 As its name implies, a multidimensional array is one that is defined by any number of dimensions, such as a 2-dimensional array that has n rows and m columns (n × m). Java does not truly support multidimensional arrays, but does support arrays of arrays - which will suffice for all practical purposes; as such, you must always specify the first dimension when declaring a "multidimensional" array in Java. However, C# inherently supports multidimensional arrays. It is likely because of this internal difference that the syntax between the two languages will vary, both in array declaration and accessing individual elements. The example below creates a 10x10 array of integers and initializes each element to its indices number multiplied together (i.e. creating a multiplication table).

import java.lang.*;


    public class MultiDimensionalHyperspeed
    {
        public static void main(String[] args)
        {
                int[][] multiArray = new int[10][10];
                for (int i = 0; i < multiArray.length; i++) {
                        for (int j = 0; j < multiArray[i].length; j++) {
                                multiArray[i][j] = i*j;
                        } // for
                } // for
                System.out.println (multiArray[4][5]);
        } // main

    } // class

using System;

namespace MultiDimensionalHyperspeed
{
    class Program
    {
        static void Main(string[] args)
        {
            int[,] multiArray = new int[10,10];
            for (int i = 0; i < multiArray.GetLength(0); i++)
            {
                for (int j = 0; j < multiArray.GetLength(1); j++)
                {
                    multiArray[i, j] = i * j;
                } // for
            } // for
            Console.WriteLine(multiArray[4, 5]);
        } // Main
    } // class
} // namespace

Note that the GetLength( ) method of the C# example returns the length of the specified dimension. For example, GetLength(0) returns the length of the first dimension (in this case, 10) and GetLength(1) returns the length of the second dimension (again, 10); naturally if there were a third dimension in this array, its length could be accessed by calling GetLength(2). Compare this with the code found in the Java example. The code queries for the number of arrays in the array via multiArray.length and then queries for the length of each individual array via multiArray[i].length. As a final note, the inner and outer loops in the Java example also work for jagged arrays...

Jagged arrays

Arrays can be jagged (sometimes called ragged) in both C# and Java. Recall that a jagged array is when the dimensions of the array are not uniform. In both languages, these are implemented as an array of arrays. Because the syntax for jagged arrays is nearly identical in both languages, they are only briefly addressed here. Below is an example of code that uses jagged arrays. Note that when the array is created, only the first dimension (specifying the number of internal arrays) is declared - allowing us to individually specify the length of the each internal array. Specifying the second dimension creates a "multidimensional" array in Java, but is not allowed in C#.

import java.lang.*;


    public class JaggedLilPill
    {
        public static void main(String[] args)
        {
                // Declare the array
                int[][] jaggedArray = new int[10][];

                // Initialize each array. Here, we have a "triangle" array
                for (int counter = 0; counter < jaggedArray.length; counter++){
                        jaggedArray[counter] = new int[counter];
                }

                // Fill in the multiplication table
                for (int i = 0; i < jaggedArray.length; i++) {
                        for (int j = 0; j < jaggedArray[i].length; j++) {
                                jaggedArray[i][j] = i*j;
                        }
                }
                System.out.println (jaggedArray[4][3]);
        } // main  
    } // class

using System;

namespace JaggedLilPill
{
    class Program
    {
        static void Main(string[] args)
        {
            // Declare the array
            int[][] jaggedArray = new int[10][];

            // Initialize each array. Here, we have a "triangle" array
            for (int counter = 0; counter < jaggedArray.Length; counter++)
            {
                jaggedArray[counter] = new int[counter];
            }

            // Fill in the multiplication table
            for (int i = 0; i < jaggedArray.Length; i++)
            {
                for (int j = 0; j < jaggedArray[i].Length; j++)
                {
                    jaggedArray[i][j] = i * j;
                }
            }
            Console.WriteLine(jaggedArray[4][3]);
        } // Main
    } // class
} // namespace

 

Collections

Many languages, such as Java, C# and C++ include libraries of commonly-used data structures, such as linked lists, binary search trees, sets, dictionaries and hashes. The data structures are fairly robust and include common algorithms such as finding the min and max elements, shuffling, sorting and so on. As a programmer, you will most likely use the data structures found in these libraries as opposed to writing your own (unless you have a specific need to do so).

C# collections are accessed by including the System.Collections (and sometimes System.Collections.Generic) namespaces. Common data structures in System.Collections include an ArrayList, HashTable, Queue and Stack. In Java, most of these equivalents can be accessed by importing java.util.*.  Two (very) common data structures are the ArrayList in C# and the Vector in Java. These polymorphic data structures accept anything of type Object (which just about everything is) and require an explicit typecast to retrieve the information - specifically from type Object back to the data type of the original variable. The example below shows an example of using these lists. Note that ArrayLists can be accessed in an array-like manner whereas Vectors use the elementAt() method.

import java.lang.*;
import java.util.*; // Access the data structures


    public class RockOn
    {
        public static void main(String[] args)
        {
                // Declare the list
                Vector leastFavoriteArtistsList = new Vector();

                // Add some "artists"
                leastFavoriteArtistsList.add ("Clay Aiken");
                leastFavoriteArtistsList.add ("Cher");
                leastFavoriteArtistsList.add ("Paris Hilton");

                // Query for the first artist
                String s = (String)(leastFavoriteArtistsList.elementAt(0));
                System.out.println (s + " is awful");
        }
    }

using System;
using System.Collections; // Access the data structures

namespace RockOn
{
    class Program
    {
        static void Main(string[] args)
        {
            // Declare the list
            ArrayList leastFavoriteArtistList = new ArrayList();

            // Add some "artists"
            leastFavoriteArtistList.Add("Clay Aiken");
            leastFavoriteArtistList.Add("Cher");
            leastFavoriteArtistList.Add("Paris Hilton");

            // Query for the first artist
            string s = (string)(leastFavoriteArtistList[0]);
	    Console.WriteLine (s + " is awful");
        }
    }
}

Output:

Clay Aiken is awful

... but we already knew that...

Is there a better way? 

Working with the "built-in" data structures saves developers a lot of time (which is quite wonderful) and offers flexibility in the kind of data that we can store. However, the flexibility comes at the cost of having to typecast when querying/retrieving data (like in the example above) - which is also prone to error. Type-casting is also somewhat slow. But these problems can be overcome when you know ahead of time that the data you are placing in the data structure is all the same type.

In such cases, it is possible to work with generics (also called parameterized types)- which are data structures that can work with just about any kind of data. Generics are available in C#, and were first included in the release of Java 1.5 (Java was retrofitted to support them).  The only catch in working with them is that the data type must be declared when the data structure is declared. The example below is identical to the example above, except that it uses generics. This is apparent in the variable declaration where the type is specified in the less than < and greater than > symbols. Also notice that there is no explicit typecast need because of this. Finally, C# programmer should note that it was necessary to use System.Collections.Generic.

import java.lang.*;
import java.util.*; // Access the same data structures


    public class RockOn2
    {
        public static void main(String[] args)
        {
                // Declare the generic list
                Vector<String> leastFavoriteArtistsList = new Vector<String>();

                // Add some "artists"
                leastFavoriteArtistsList.add ("Clay Aiken");
                leastFavoriteArtistsList.add ("Cher");
                leastFavoriteArtistsList.add ("Paris Hilton");

                // We no longer have to typecast!
                String s = leastFavoriteArtistsList.elementAt(0);
                System.out.println (s + " is awful");
        }
    }

using System;
using System.Collections;	  // This line is no longer needed, but...
using System.Collections.Generic; // We have to include this now!

namespace RockOn2
{
    class Program
    {
        static void Main(string[] args)
        {
            // Declare the generic list
            List<string> leastFavoriteArtistList = new List<string>();

            // Add some "artists"
            leastFavoriteArtistList.Add("Clay Aiken");
            leastFavoriteArtistList.Add("Cher");
            leastFavoriteArtistList.Add("Paris Hilton");

            // We no longer have to typecast!
            string s = leastFavoriteArtistList[0];
	    Console.WriteLine (s + " is awful");
        }
    }
}

 

C# to Java Summary:

Java to C# Summary:

 

Input and Output (I/O)

Input and Output (or I/O) is so fundamental, we probably should have covered it first. However, the problem is that dealing with I/O is usually complex, so it makes sense to shove it in a later discussion. Well, the time has come...

You're probably already aware of how to post information to the console from the previous examples - using either Console.WriteLine() in C# or System.out.println() in Java. Both of these methods allow variables of different data types to be displayed, whether they are primitive or not. As mentioned previously, both languages have methods that do not drop down to the next line (i.e. no carriage return) after printing; those methods are Console.Write() in C# and System.out.print() in Java. In order not to belabor the point (or insult your intelligence), this will be the last discussion on printing to the console. Reading in from the console is a different matter and requires two very different discussions...

Reading input from the keyboard in C#

When building command line (console) applications, at some point, you will need to read information in from the user. Reading strings from the user in C# is nearly trivial. Here's a very small code snippet to prove that point:

Console.Write ("Enter your name: ");
string userName = Console.ReadLine();

See! It's easy! However, it is also very common to read non-string information from the user, such as their name. The problem is that Console does not have a ReadInt() method, a ReadFloat() method, a ReadDouble() method and so on - and for good reason. Imagine how long the list of available methods could become as new data types became available. Instead it is necessary to convert the strings you read into the appropriate data type.  Fortunately, there are several built-in class you can use, such as Byte, Int16, Int32, and Double.  All of these classes have a Parse() method that takes in a string and returns the appropriate data type. The example (below) shows how to read in an int from the user in C#.

using System;

namespace ReadingInts
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Enter your age: ");
            // Read a string, such as "21"
            string temp = Console.ReadLine();
            // Interpret the string as an int
            int realValue = Int32.Parse(temp);
        }
    }
}

Reading input from the keyboard in Java

You may be asking yourself: "If there's a System.out, is there a System.in also?"  The answer is "yes"! System is a class that supports standard input and output (from the keyboard and to the console). in is a member of system which is of type InputStream. The issue is that input streams can only read a number (or series of numbers) via a call to the read() method. Here's a look at the method signature (prototype) that we'll be using.

abstract int read ();

Notice the int return type? Well, according to the API, read() returns "the next byte of data from the input stream". To further complicate things, all reading from an InputStream is required to be wrapped in a try/catch statement. If you're unfamiliar with this concept, it can be generally described as trying (attempting) to execute a block of code, and if something screws up, something called an Exception is thrown.  You have the ability to catch that Exception and handle it appropriately - cleaning up any mess that may have occurred. And a quick note about Java I/O: you always have to do this because you never know when the network will go down, a file doesn't exist, or the user types something in the wrong format.

All that being said, we're ready to see our first, not-exactly-working-the-way-it-should program...

import java.lang.*;

    public class MyJava
    {
        public static void main(String[] args)
        {
                int userAge = -1;
                System.out.println ("Enter your age: ");
		
		// Try to read from the keyboard
                try {
                        userAge = System.in.read();
                }catch (Exception e) {
			// This only executes if something messed up!
                        System.out.println ("Couldn't read");
                }
                System.out.println ("You are " + userAge);
        }
    }

Assuming we typed in 21 as our age, the output of the program is:

Enter your age: 
21
You are 50

What happened? The problem is that even though we were reading in a byte, it read in the first thing the user typed in - which was the character '2'. Yes, you heard correctly: the character - and it was in ASCII; follow that link and you'll see that, indeed, the ASCII value of the character '2' is 50. So in summary, all that code got us the ability to read one character, which was in ASCII. We didn't even make it to the '1'...

Does this mean you need to loop through all of the characters that you read in, convert from ASCII to base 10? Fortunately, no. Read on.

Enter the InputStreamReader and BufferedReader

Knowing that System.in is an InputStream, what we need is a translator of sorts. What we'd really like to be able to do is read entire Strings (like Console.ReadLine()). To do that, we'll start by creating an InputStreamReader. This class is designed to read from an InputStream and convert what it reads into Unicode (which is similar to ASCII, but uses 16-bits to represent each character instead of 8. This allows support for languages other than English).

Next, we can create a BufferedReader which reads from an InputStreamReader and packages everything it reads into a nice, convenient String! This is done via a call to readLine().

The code below lists each individual step in the process of reading a String from the user. Note that it is necessary to import java.io.*;

import java.lang.*;
import java.io.*;	// We need to include this now

    public class MyJava
    {
        public static void main(String[] args)
        {
                InputStreamReader isr;
                BufferedReader br;
                String userName = "";

                System.out.println ("Enter your name: ");
                try {
                        isr = new InputStreamReader (System.in);
                        br = new BufferedReader (isr);
                        userName = br.readLine();
                }catch (Exception e) {
                        System.out.println ("Couldn't read");
                }
                System.out.println ("Your name is " + userName);
        }
    }

Of interest is the call to readLine(). Reading from br forces it to read from isr, which forces isr to read from System.in(). This is perfect example of the data layering process that is commonly found in Java I/O.  Realize that most often, the BufferedReader is created in one statement:

BufferedReader br = new BufferedReader (new InputStreamReader(System.in));

Reading ints, floats and doubles

Now that you better understand data "layering" in Java, it is easier to explain reading in numbers.  First, if you are reading in from the keyboard and have read in a String that was intended to be a number (e.g. the user's age), the String can be converted to an int via a call to Integer.ParseInt(). Similarly, a String can be converted to a double by a call to Double.ParseInt(). The code below is a quick example of this.

import java.lang.*;
import java.io.*;	// We need to include this now

    public class MyJava
    {
        public static void main(String[] args)
        {
                InputStreamReader isr;
                BufferedReader br;
                String userInput = "";
		int userAge = -1;

                System.out.println ("Enter your age: ");
                try {
                        isr = new InputStreamReader (System.in);
                        br = new BufferedReader (isr);
                        userInput = br.readLine();
			userAge = Integer.ParseInt(userInput);
                }catch (Exception e) {
                        System.out.println ("Couldn't read");
                }
                System.out.println ("You are " + userAge);
        }
    }

However, if you are reading from a file that contains integers, shorts, double, etc., though it is beyond the scope of this unit, you will need to look into the DataInputStream class, which has methods to readByte(), readChar, readDouble() and so on.

Life made easy: reading from JOptionPane

One option you have (no pun intended) is to read Strings using the graphical JOptionPane - which is found in the javax.swing package. It can be done in one line by calling the showInputDialog() method. Below is an example of prompting the user for their name and reading it in.

import java.lang.*;
import javax.swing.*;  // Don't forget to import this

    public class SwingIt
    {
        public static void main(String[] args)
        {
                String userName = JOptionPane.showInputDialog(null,
                        "What is your name?",
                        "Enter your name",
                        JOptionPane.QUESTION_MESSAGE);
        } // main
    } // class

 

C# to Java Summary:

Java to C# Summary:

 

Classes

Defining classes and creating objects

Because both Java and C# are Object-Oriented languages, it only makes sense that a programmer has the option of creating his or her own data types (classes), and can use "advanced" OOP techniques such as inheritance, interfaces, and polymorphism. Syntactically they are similar, though there are minor differences when it comes to creating accessors and modifiers for a classes attributes (or fields/members).

In general, a class can be defined with the following template:

class <class name> {
    // Attributes
    // Constructor
    // Methods
}

As an example, and without further ado, we present class Dog:

import java.lang.*;



    class Dog 
    {
	// Attributes
        private int weight;
        private String name;
        private boolean rabid;

        // Constructor
        public Dog (int weight, String name){
                this.weight = weight;
                this.name = name;
                rabid = false;
        }

        // Accessors and modifiers - only one shown here
        String getName() {
                System.out.println ("get called");
                return name;
        }
        void setName (String newName) {
                System.out.println ("set called");
                if (newName != "Fluffy") {
                        name = newName;
                }
        }
    }







    public class HowMuchIsThatDoggy
    {
        public static void main(String[] args)
        {
                Dog d1 = new Dog (65, "Spike");
                // use the modifier
                d1.setName ("Fluffy");
                // use the accessor
                System.out.println (d1.getName());
        }
    }
using System;

namespace HowMuchIsThatDoggy
{
    public class Dog
    {
	// Attributes
        private int weight;
        private string name;
        private bool rabid;

        // Constructor 
        public Dog (int weight, string name)
        {
            this.weight = weight;
            this.name = name;
            rabid = false;
        }

        // Accessors and modifiers - only one shown here
        public string Name
        {
            get
            {
                Console.WriteLine("get called");
                return name;
            }
            set
            {
                Console.WriteLine("set called");
                if (value != "Fluffy")
                {
                    name = value;
                }
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Dog d1 = new Dog(65, "Spike");
            // Use set
            d1.Name = "Fluffy";
            // Use get
            Console.WriteLine(d1.Name);
        }
    }
}

As you can see, defining a class in both languages is very similar. Each language uses the class keyword and enables the programmer to include attributes, constructors, and methods. They also include modifying keywords such as public and private, which can be placed before class, method and variable declarations. Of interest is the constructor (which is used to initialize each attribute). The keyword this is supported in both languages and is used to disambiguate which variable is being referenced - though its use is frequently misunderstood by programmers. For example, look at the constructor. When referring to the weight variable in the constructor, the programmer could be referring to the attribute or the parameter (since they have the same name). In this case, weight by itself refers to the most-local weight (which is the parameter and not the attribute). By prefacing a variable with the keyword this, we are referring to the attribute of the class. Thus the statement this.weight = weight; assigns the weight attribute the value of the weight parameter that was passed in.

In main, you can see that declaring variables of type Dog is identical. d1 in both cases is a reference type and therefore supports the '.' operator (i.e. to call methods in the class, you will use the template <variable name>.<method name>() as described in the section on methods).

Accessors and Modifiers

Conceptually, both languages support the notion of accessors and modifiers (also called setters and getters). Notice that the attributes of the class are marked private, meaning that their scope (or visibility) can be seen only within the class. If a piece of code attempts to access them from outside the class (e.g. main), the compiler will complain. The reason marking attributes as private is done is for good design - as it allows the designer of the class to put reasonable constraints on how the attributes are queried and set. For example, if someone asks me my weight, I could actually "return" them my weight minus 10 pounds; that's a lie, of course, but I still have that option.  I could do the same thing with my age. If some tries to set the age of a person (programmatically) to say, 300, obviously this is beyond the bounds of a normal lifespan - and we can handle it by setting age to something more reasonable (say, 100) or ignoring the request altogether.

In Java, accessors and modifiers are regular methods and can be called whatever you like. However, most programmers follow the convention of prefacing the attribute name with "get" for accessors and "set" for modifiers. You can see this in the example above: we have an accessor for the name attribute called getName() and a modifier called setName().

In C#, the syntax is much different. First, we declare a publically visible "attribute" that is the same name as the private attribute, but capitalize the first letter; in this case, it would be Name. Note that the syntax for this is almost like that of a method (because of the curly braces). Inside this declaration is a get/set pair - each of which need a little explanation. As its name suggests, the set portion of this code is called any time the publically visible attribute (Name) is modified in any way (via assignment or other operator such as ++). In the example above, main attempts to set the Name of d1 to "Fluffy" through the assignment statement and this triggers a call to set.  The literal string "Fluffy" is placed into the keyword value, and becomes available inside the set portion of the code - at which point we can do whatever we need to with it.  The get method is triggered any time a query for the publically available attribute (e.g. Name) is referenced but not modified (i.e. a reading of the variable). In a get statement, you can return anything you like but is most often the attribute itself.

In the example above, we only include one accessor/modifer pair, though realistically one pair should exist for each attribute that you want to be publically visible. In the example above, the accessor simply returns the value of the private attribute. The modifier, on the other hand, looks at the value that is being passed to ensure that the name attribute will not be changed to "Fluffy"; this would be a form of abuse and we can prevent it - even if it is only a virtual Dog. In this case, main tried to set d1's name to "Fluffy" and the request was simply ignored. When the dog's name is printed out later, the name remains "Spike".

The final output of the code is:

set called
get called
Spike

 

C# to Java Summary:

Java to C# Summary:

 

For the Java Folks: The XNA Game Loop

One of the more difficult concepts for students who are transitioning from Java to C# is in understanding the basics of XNA.  As you are probably aware, XNA is a Microsoft technology - very similar to DirectX - that provides robust support and common code for developing 2D and 3D video games; XNA games that you develop can be put onto an XBox 360 and played. As of this writing, XNA 4.0 is in Beta and due for release this year (2010).

It is highly recommended that you watch the video tutorials on XNA - as they walk you through how to create projects, display sprites, handle input, and so on. Nevertheless, we provide a cursory overview of XNA from a Java point of view - starting with the concept of callback methods.

Callback methods and the XNA skeleton

Perhaps the most difficult transition for Java folks is in understanding how XNA code executes. Up until this point, you have likely been creating programs from scratch - printing to the console and reading from the keyboard. You started with the Java skeleton (public static void main (String[] args)) and went on from there. Tracing through the code was fairly straight-forward because the entry point to the program was always main and if any methods were invoked (called), you could jump to that method, execute it, and then return back to main.

XNA is slightly different. While everything just described is still true, it is covered up; you never see main unless you dig around. Instead, a default project stubs in a series of callback methods - which are methods that are called from some other part of the program that you rarely (if ever) see. This concepts is also very similar to the way that OpenGL works (if you have experience in that).  Below is a stripped down version of the default source code that you get when creating a new XNA project (for simplicity, many of the using statements and comments have been removed since they do not contribute to the discussion).

 

>
using System;
using Microsoft.Xna.Framework;
// Other "using" statements were removed for simplicity...

namespace MyFirstGame
{
    
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
        }

        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            base.Update(gameTime);
        }
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            base.Draw(gameTime);
        }
    }
}

While it may not be exactly what you are used to, we can still make some sense of this code.  Looking at the code, you can see that a class called Game1 has been created and it inherits from Microsoft.Xna.Framework.Game - so yes, we are still using OOP. The class has a constructor and two attributes (a GraphicsDeviceManager and a SpriteBatch which are described in more detail in the video tutorials). These attributes may seem strange to you (since you probably have been working with simple data types like ints and Strings), but think about the kinds of attributes a game would have. There would sprites (images), sounds, x and y positions (in Vectors) and even video.

Past this point are the callback methods; and notice there is no main! The callback methods include Initialize(), LoadContent(), UnloadContent(), Update() and Draw(). All of these methods are called at different points during the game's execution; don't worry about what program is calling them because it is all hidden away from you. Though some of these methods are self-explanatory, here's a brief summary of what these methods are used for and when they are called:

Java to XNA Summary:

 

Appendix A: Getting Started with IDEs, APIs and Other Resources

Before diving straight into code, it is important to get your system configured for development. If you haven't done so already, you will need to download an IDE (Integrated Development Environment) for either Java or C#. For Java, SPSU currently uses jGrasp+JDK (Java Development Kit) and for C#, it uses Visual Studio 2008+XNA. The instructions for installation are quickly shown below.

Quick Resources

Getting started with Java:

C#/XNA

Installing the JDK and jGrasp

To start coding in Java, you will need the JDK. It contains all of the libraries, runtime environemnt and the compiler! However, unless you're familiar with compiling from a command-line environment (e.g. DOS or Unix), you will likely want to install an IDE (in this case, jGrasp or NetBeans) which sits on top of the JDK and makes calls to it (such as compiling calls).

You can download the JDK from http://www.oracle.com/technetwork/java/javase/downloads/index.html (or more specifically at this site); make sure you check with your instructor before doing this - taking special note on which version to install. You will need to specify the language and operating system you will be using. The JDK is approximately 75MB. For the most part, click Next, Next, Next (blah, blah, blah)... and it will install itself.

After you have installed the JDK, you can install an IDE. jGrasp is an IDE that was developed at Auburn University. It can be downloaded at http://www.jgrasp.org/ (or more specifically at this site). Again, if you haven't done so, make sure you download AND install the JDK before installing jGrasp. During download, filling out the form is optional, but make sure you select the correct operating system.  The download is approximately 5MB. It can be installed by click Next, Agree, Next, Next (blah, blah, blah).

Java API is sorted by the package it is in, which can be daunting.  The link can be found at http://download-llnw.oracle.com/javase/6/docs/api/overview-tree.html. In general, you will start with a package and drill down to the information you are looking for. Given the number of classes that are available in Java and the organization of the layout, you may be better off searching via Google and then referring to the API to see the methods that are available. Your instructor may also have additional resources to help you navigate this monster...

Installing Visual Studio and XNA

To begin, you will need to download Visual Studio - which requires you to login. This process isn't exactly straightforward, but you can find the directions for doing so at http://cse.spsu.edu/cslab/SoftwareForStudents/MSDNaa/default.html. Realize that Visual Studio is at no cost to CSE students because the school has purchased licenses.

You will want to download and install Visual Studio 2008 (even if 2010 is available) and then XNA 3.1. This will change soon, but until the kinks are worked out of the system, downloading VS 2010 and XNA 4.0 is risky. You can try it if you like (and it will likely work), but this can cause problems during submission (because chances are you instructor hasn't installed 2010 yet and may be unwilling to do so). And though it's relatively easy to upgrade a 3.1 project to 4.0, it's much harder to convert a 4.0 project to 3.1 (which would require you to create a project in 2008, copy over source code files and recompile to verify).

Note: the first time that you run Visual Studio, it often asks which language you would like to be the default. This is because the IDE can configure itself differently based on the language you most commonly use - and essentially exposes different things (such as views) to the programmer. It is assumed that if you are reading this unit, you will want to select C#. You will also likely see a newsfeed of Microsoft events and articles - which appears on the opening screen. It's OK to shut this tabbed window down if you like. Or if you prefer to leave it open, that's OK too...

Creating a Project in Visual Studio

Once you've installed and started Visual Studio (2008), you will likely want to create a new project. It's quite trivial. Go to the File menu and the select New Project (abbreviated as File->New Project).

Creating a new project in Visual Studio

While this step isn't terribly difficuly to do, you will need to know what kind of project you want to create. Selecting the right kind of project is crucial - since Visual Studio will stub in a majority of the skeleton code that you will need. When working with C#, you will typically create one of three kinds of projects:

  1. A Command-Line Application. This runs in the console (a giant black window with text in it). The projects aren't very exciting, but are a great way to quickly test concepts out. This kind of project is highlighted on the window on the left (below).
  2. A Windows Form Application: If you want to create a graphical application (with Buttons, Labels, Textfields and so on), you will choose this option. You can see this option in the left window (below).
  3. An XNA (3.1) project. This is your obvious choice if you want to create a game. From the list under "Visual C#", you will see XNA Game Studio 3.1. Clicking that will bring up the window on the right (below). Notice that when creating an XNA project, you can target different platforms including the Xbox 360, the Zune (a mobile device) or the Windows platform itself.

Chosing a project type  Chosing an XNA project

 

As shown in the window on the right (above), you will need to:
  1. Select the broad category of project want to create, such as Windows or XNA Game Studio 3.1.
  2. Select the specific type of project, such as Console, Windows Form Application or in the case of XNA Game Studio, a Windows Game (3.1)
  3. Give the project a name in the name field. Though it is selected by default, ensure that the Create directory for solution checkbox is checked.
  4. Press the OK button. 

Working with Visual Studio

Before diving into coding, you should familiarize yourself with your new environment. The IDE is comprised of several windows that are visible at times and invisible other times. Sometimes, windows can even be tucked away where only a tab is visible.  But in general, the layout will look similar to the one below.

The Visual Studio IDE

The solution window shows the hierarchical layout of the files associated with this project. A project is organized close to the same way that your operating system is - being comprised of files and folders. By clicking on the A plus symbol symbol (the plus symbol) you can expand the folder to see its contents. By right-clicking on files and folder, a menu will be provided that enalbles you to do file-specific actions. Further, double-clicking a file in the solution window opens it in the editing window. If the solution window isn't visible, it can be opened by (quickly) pressing CTRL+W and then the S key, or by going to View->Solution Explorer. Note: if you look closely in the image above, you can see the Toolbox tab to the left of the solution window.

The editing window is for manipulating individual files. This view will change - depending on the kind of file that is being edited. In the example above, source code is currently being edited.  However, if you were to double-click on an image, it will pull up an image editor. One thing to notice is that each of the windows in the editor section have an associated tab. By clicking on the tab, you can quickly switch between multiple (open) files - which is very convenient as your project begins to grow. Far to the right of the window is the The X icon icon - which allows you to close this tab. If the editing window isn't open, try double-clicking on a file.

The properties window is useful when you are working with windows forms.This exposes several of the attributes of components on the screen, such as color, font information, text, and so on - which will allow you to customize each component. It can be opened by (quickly) pressing CTRL+W and then the P key, or by going to View->Properties Window. Note: if you look closely in the image above, you can see the Toolbox tab to the left of the solution window.

Finally, the output window is where you will see any IDE-generated messages, such as errors when things don't compile. If it's not already visible, this window can be opened by pressing CTRL+W and then the O key.

Compiling and Running

Sooner or later, you'll need to compile your code and run it. This can be done in a single step by pressing the triangular green "play" button on the compiling toolbar (above the editor - see image below); alternatively, you can press F5.  Before you do so, look immediately to the right of that button and you'll see the Build Mode of your project.  Realize that most of the time you will want to compile and run in Debug mode, and when you're ready to release your program to the public, you can switch it into Release mode. One other thing to notice about this toolbar is that it contains many of the common file operations (such as saving your files, adding new items to the project) as well as making windows visible (such as the toolbox or solution explorer).

The toolbar
 

Most of the time, you can get away with pressing F5. However, if you are working with a console application, you will notice that immediately after your program runs, the window will close! This makes it hard to view the output of your program (and is quite frustrating).  To overcome this, run your program using CTRL+F5. You'll notice that running your program this way pauses the program after it runs, and appends the text "Press any key to continue..."  The answer is always no - I won't tell you where the "any" key is on your keyboard.

Press any key to continue

Appendix B: Under the Hood

Virtual Machines

Though it is beyond the scope of this unit to be talking about the technical differences between C#'s and Java's virtual machines, you should understand how virtual machines work in general.  When you compile code in either language, the code is put into an intermediate form. For Java, this is called byte code and for C# it's called IL (for intermediate language - sometimes called CIL for Common Intermediate Language or even MSIL for Microsoft Intermediate Language). For all practical pursposes, byte code and IL are equivalent. They are both "half-compiled" in a sense in that you cannot run them (i.e. it's not an executable). So how does this all work then?

The trick is in the virtual machine - which is responsible for taking the intermediate code (byte code or IL) and running it in a platform-specific way. Thus, there is a virtual machine out there for each operating system - meaning there's a separate virtual machine for Windows, one for Linux, one for SGI, one for Mac, and so on. The image below depicts how this works.

Virtual Machine Architecture

 
So, for example: imagine that you have created a great program that you would like to share with your friends. The only problem is that one is a Mac user, the other a Windows user and the last a hard-core ultra cool Linux user. The process goes like this. First you compile your source code into an intermediate form (either byte code or IL) as shown in the image above. You can then send this intermediate code to your friends (say, via email or the web). This code is then handled by the virtual machine which then makes platform-specific operating system calls. For example, the virtual machine for the Mac is responsible for taking the intermediate code and translating into something that the Mac OS X operating system understands. The virtual machine for Windows takes that same intermediate code and translates it into something that the Windows operating system understands.  As new operating systems come along, you can see that it's "simply" a matter of creating a new virtual machine for it to do the interpretation!

Garbage Collection

Similar to the discussion of virtual machines, garbage collection is a little beyond the scope of this unit. However, it's critical that you understand what is going on in memory, what garbage collection is, and how it works.

One of the "new" features available in many modern programming languages is known as a garbage collector. But before we talk about that, we probably need to gain a better understanding of what garbage is. If you recall from the section on parameter passing, creating a variable of a particlar class actually creates a reference to a chunk of memory. Imagine we have a line of code like the following:

Dog d1 = new Dog();

Then memory would look something like the following:

Before creating garbage 

The question is then this. What would happen if we executed the following line of code?

d1 = null;

Then memory would look like the following:

A piece of garbage is collected 

So now you can see the basic problem.  Our variable d1 is pointing to nothing (null) and the chunk of memory that was previously referenced by d1 is left without anything pointing to it! Unfortunately, this means that there is no possible way to refer to that chunk of memory any longer, which creates a piece of garbage. Though this is a big problem for languages like C/C++, this isn't a problem for languages like Java or C# because they have a garbage collector!  The responsibility of the garbage collector is to periodically clean up memory that is no longer being referenced - like in our example above. When the garbage collector is run, it reclaims memory for the virtual machine so that the next time you try asking for more memory using the new operator, chances are you'll get it. This is something you may not appreciate if you've never programmed in C++, but when you begin to have memory leaks (creating pieces of garbage in languages that don't have a garbage collector), you'll begin to appreciate what's going on here. For more information on garbage collection, check out http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29.