2007/12/12

C# for Java Developers

C# for Java Developers

At first glance, Java developers might not get particularly excited about C# code, because of the
syntactical similarity between it and Java. However, look more closely and you will see subtle yet significant differences: features such as operator overloading, indexers, delegates, properties, and type safe enumerations in C#.
This appendix focuses on applying much-loved Java programming tricks to C# code, highlighting features that C# adds to the picture, and pointing out tricks that C# cannot do (although you won’t find many of those). Of course, we assume that as a reader of this appendix, you are a professional Java developer; so we will not go into too much detail when describing the Java language.

Starting Out
Let’s take a look at the infamous “Hello World!” example in Java:

public class Hello {
public static void main(String args []) {
System.out.println(“Hello world! This is Java Code!”);
}
}
The corresponding C# code for this is as follows:
using System;
public class Hello
{

could place a file containing this namespace anywhere within the directory as long as the CLR recognizes
it. Therefore, it also enables us to call the file containing these classes anything we wish (it doesn’t
have to be the same name as the class as in Java); we can have more than one public class defined per
file; and we can split the classes defined in this namespace into different files in different parts of the
directory structure, as long as the namespace declaration appears in each of the files.
We can also introduce multiple namespaces in the same file with no restriction. We could, for example,
add the definition of a new class and place it in a new namespace in the same file and still not be outside
the bounds of the language:
namespace java2csharp.csharpsamples
{
using System;
public class Hello
{
public static void Main(string [] args)
{
System.Console.WriteLine(“Hello world! This is C# code!”);
}
}
}
namespace java2csharp.morecsharpsamples
{
using System;
public class AnotherHello
{
public static void Main(string [] args)
{
System.Console.WriteLine(“Hello again! This is more C# code!”);
}
}
}
As we pointed out in the previous section, classes from a particular namespace can be imported into
another namespace with the using keyword. We can see that we import classes from the System namespace
(the top level .NET Base Class namespace) into both namespaces above. We can also import classes
from other namespaces directly into our classes by referring to the imported class using its full name
(namespace included), in a similar way to using direct referencing of classes in Java code.
Namespaces may also be defined within other namespaces. This type of flexibility is impossible in Java
without having to create a subdirectory. We could change the previous example so that the AnotherHello
class is in the java2csharp.csharpsamples.hellosamples namespace:
namespace java2csharp.csharpsamples
{
namespace hellosamples
{
using System;
public class AnotherHello
{
public static void Main(string [] args)
public static void Main(string [] args)
{
System.Console.WriteLine(“Hello world! This is C# code!”);
}
}

The first thing that you’ll notice is that the two appear to be very similar syntactically and both languagesare case-sensitive. C# is object-oriented like Java, and all functionality must be placed inside aclass (declared by the keyword class). These classes can contain methods, constructors, and fields justas Java classes can, and a C# class can inherit methods and fields from another class or interface as inJava. The implementation of classes and methods is similar in both languages.C# code blocks are enclosed by braces just as in Java. The entry point to a C# application is the staticMain() method, as required by the compiler (similar to Java but note the uppercase “M”). Also note thatonly one class in the application can have a Main() method. Similar to Java, the static keyword allowsfor the method to be called without creating an instance of the class first. For the Main() method in C#you have the choice of either a void or int return type. void specifies that the method does not return avalue and int specifies that it returns an integer type.The using keyword in C# corresponds to the import keyword in Java. Therefore, in the C# code above,we are essentially importing the C# equivalent of a class package called System. In C#, a class package iscalled a namespace, and we will look more closely at these in the next section.Note that although we have written it with a lowercase s here, in C# the string type can also be writtenwith a capital S as String. You will also notice that the array rank specifier ([]) has been shifted from infront of the args variable in the Java example, to between the string type and args variable in the C#sample. In fact, this specifier can occur before or after the variable in Java. However, in C#, the arrayrank specifier must appear before the variable name because an array is actually a type of its own indicatedby type []. We’ll discuss arrays in more depth a bit later.Finally, as you might expect, the names of methods tend to differ between the languages. For example,in Java we would use System.out.println() to display text in the command console. The equivalentto this method in C# is System.Console.WriteLine().

Compiling and Running C#

we noted that like Java code, C# source code is compiled in two stages: first toIntermediate Language (IL), and then to native code. To run the previous C# code, you need to save itwith an appropriate filename (for example, HelloWorld) and file extension .cs, and then compile it to ILusing the csc command:csc HelloWorld.csThe next step is to compile the IL to native code and run the example. To do this, just type the name ofthe file, without the extension (as we would with Java code):HelloWorldHello world! This is C# code!NamespacesWhile Java classes reside in logical divisions referred to as packages, C# (and other managed) classes aregrouped together into namespaces. Packages and namespaces differ significantly in their implementation.A Java class that you want to make part of the com.samples package, for example, must have packagecom.samples; as the first line of code in the file. This is, of course, excluding any comments. Any code

within that file automatically becomes a part of the specified package. Also, a Java package name is associated with the folder containing the class file in that they must have the same name. The com.samples package must therefore be in class files that exist in the com/samples folder. Let’s take a look at some

examples of how packages work in Java:

package java2csharp.javasamples;
public class Hello {
public static void main(String args []) {
System.out.println(“Hello world! This is Java Code!”);
}
}

The following list provides examples of how the previous code could be referenced or executed. This listassumes that the class file has been made available to the JRE:

❑ From the command line:
java java2csharp.javasamples.Hello
❑ As a direct reference in the code:
public class Referencer {
java2csharp.javasamples.Hello myHello = new java2csharp.samples.Hello();
❑ By utilizing the import directive one could omit fully qualified package names, so Referencer
could also be written as:

import java2csharp.javasamples.*;
public class Referencer {
Hello myHello = new Hello();
}
Wrapping a class in a namespace is achieved in C# by using the namespace keyword with an identifier,
and enveloping the target class in brackets. Here is an example:
namespace java2csharp.csharpsamples
{
using System;
public class Hello
{
public static void Main(string [] args)
{
System.Console.WriteLine(“Hello world! This is C# code!”);
}
}
}

As you can see, we delimit layers of namespaces using the . operator, as in Java. Note that C# does not require an asterisk (*) needed in C#—applying the using directive implicitly imports all elements of the specified namespace. You will also have noticed the major difference from Java here: the use of namespace parentheses in which we place classes associated with the namespace. The advantage of using the parentheses like this is that we then disassociate package names from directory structures: feasibly we


could place a file containing this namespace anywhere within the directory as long as the CLR recognizes it. Therefore, it also enables us to call the file containing these classes anything we wish (it doesn’t have to be the same name as the class as in Java); we can have more than one public class defined per file; and we can split the classes defined in this namespace into different files in different parts of the directory structure, as long as the namespace declaration appears in each of the files. We can also introduce multiple namespaces in the same file with no restriction. We could, for example, add the definition of a new class and place it in a new namespace in the same file and still not be outside the bounds of the language:

namespace java2csharp.csharpsamples
{
using System;
public class Hello
{
public static void Main(string [] args)
{
System.Console.WriteLine(“Hello world! This is C# code!”);
}
}
}
namespace java2csharp.morecsharpsamples
{
using System;
public class AnotherHello
{
public static void Main(string [] args)
{
System.Console.WriteLine(“Hello again! This is more C# code!”);
}
}
}
As we pointed out in the previous section, classes from a particular namespace can be imported into another namespace with the using keyword. We can see that we import classes from the System namespace (the top level .NET Base Class namespace) into both namespaces above. We can also import classes from other namespaces directly into our classes by referring to the imported class using its full name (namespace included), in a similar way to using direct referencing of classes in Java code. Namespaces may also be defined within other namespaces. This type of flexibility is impossible in Java without having to create a subdirectory. We could change the previous example so that the AnotherHello class is in the

java2csharp.csharpsamples.hellosamples namespace:
namespace java2csharp.csharpsamples
{
namespace hellosamples
{
using System;
public class AnotherHello
{
public static void Main(string [] args)

{
System.Console.WriteLine(“Hello again! This is more C# code!”);
}
}
}
}
Java classes are part of a package; all classes created are part of the default package. C# mimics this functionality. Even if you do not declare one, a default namespace is created for you. It is present in every file and available for use in named namespaces. Just as in Java you cannot change package information, in C# namespaces cannot be modified either. Packages can span multiple files in the same folder; namespaces can span multiple files in any number of folders, and even multiple assemblies (the name given to code libraries in .NET).
Note that the default accessibility for types inside a namespace is internal. You must specify types as public if you want them available without full qualification; however, we strongly advise against this practice. No other access modifiers are allowed. In Java, internal package types may also be marked as final or abstract or not marked at all (this default access makes them available only to consumers inside the package). Access modifiers are discussed later in this appendix.
One final feature of namespaces not available to Java packages is that they may be given a using alias. using aliases make it very easy to qualify an identifier to a namespace or class. The syntax is simple. Suppose you had a namespace Very.Very.Long.NameSpace.Name. You could define and use a using

alias (here VVLNN) for the namespace as follows:
using VVLNN = Very.Very.Long.Namespace.Name;

Declaring Variables
C# follows a similar scheme of variable declaration to Java, where the declaration consists of a datatype keyword and followed by the name of the variable to hold that datatype. For example, to declare an integer (int) variable called myInt, we would use the following code:
int myInt; Identifiers are the names we give to classes, objects, class members, and variables. Raw keywords, discussed
in the next section, can neither be Java nor C# identifiers; however, in C# you can use keywords
as variable names by prefixing the name with @. Note that this exception is only with keywords and does not allow the breaking of any other rules. Although identifiers may have letters and numbers, the first letter of the identifier in both C# and Java must not be a number. Here are some valid and invalid

examples of variable declaration:

int 7x; //invalid, number cannot start identifier
int x7; //valid, number may be part of identifier
int x; //valid
int x$; //invalid, no symbols allowed
int @class; //valid, prefix @ allows it to be used as an identifier
int @7k; //invalid, prefix @ only works for keywords


Variable Naming Conventions
Java uses camel-case notation for methods, properties, and variables, meaning that they are lowercase for the first letter in the name and capital letter for the first letter of every other word in the name. The first letter of class and object names in Java are uppercase. The following snippet shows the general syntax

most Java programmers use:
int id;
int idName;
int id_name; //practiced also
final int CONSTANT_NAME; //widely adopted
int reallyLongId;
public class ClassName //every first letter capitalized
public interface InterfaceName
public void method(){}
public void myMethodName(){}

Based on the C# library classes, it is safe to make certain assumptions about C# naming conventions. A documented naming guideline for C# was not provided at the time of this writing. Each first letter of all method and property identifier names is capitalized, as is each first letter of all class and namespace names. Interfaces are preceded with an I. Variables are camel-cased, as shown in the following examples:

int id;
int idName;
public class ClassName //every first letter capitalized
public interface IInterfaceName //interface name preceded by I
public void Method(){} // first letter always capitalized
public void MyMethodName(){} // first letter of all other words capitalized
Data Types

Types in Java and C# can be grouped into two main categories: value types and reference types. As you are probably aware, value type variables store their data on the stack, while reference types store data on the heap. Let’s start by considering value types.
Value Types There is only one category of value type in Java; all value types are by default the primitive data types of the language. C# offers a more robust assortment. Value types can be broken down into three main
categories:
❑ Simple types
❑ Enumeration types
❑ Structures
Let’s take a look at each of these in turn.


Simple types
The C# compiler recognizes a number of the usual predefined datatypes (defined in the System Base Class namespace), including integer, character, Boolean, and floating point types. Of course, the value ranges of the indicated types may be different from one language to another. Below we discuss the C# types and their Java counterparts.
Integer values
C# has eight predefined signed and unsigned integer types (as opposed to just four signed integer types in Java):

C# Type Description Equivalent in Java

sbyte Signed 8-bit byte
short Signed 16-bit short
int Signed 32-bit int
long Signed 64-bit long
byte 8-bit unsigned integer n/a
ushort 16-bit unsigned integer n/a
uint 32-bit Unsigned integer n/a
ulong 64-bit Unsigned integer n/a
When an integer has no suffix the type to which its value can be bound is evaluated in the order int, uint, long, ulong, decimal. Integer values may be represented as decimal or hexadecimal literals. In the following example the result is 52 for both values:
int dec = 52;
int hex = 0x34;
Console.WriteLine(“decimal {0}, hexadecimal {1}”,dec, hex);
Character values
char represents a single two-byte long Unicode character. C# extends the flexibility of character assignment by allowing assignment via the hexadecimal escape sequence prefixed by \x and Unicode representation via \u. You will also find that you will not be able to convert characters to integers implicitly. All other common Java language escape sequences are fully supported.
Boolean values The bool type, as in Java, is used to represent the values true and false directly, or as the result of an
equation as shown below:
bool first_time = true;
bool second_time = (counter < precise =" 1.234m;" precise =" (decimal)1.234;" f =" 5.6;" f =" 5.6F;" red =" 0;" green =" 1;" blue =" 2;" internal =" Day;}" monday =" new" tuesday =" new" wednesday =" new" thurday =" new" friday =" new" working =" 131," complete =" 129," beforebegin =" 132">Preventing inheritance
In C# the sealed modifier is used to prevent accidental inheritance, because a class defined as sealed can not be inherited from. Declaring a class as final achieves the same goal. Declaring a method as final also seals it, making it impossible to override. Declaring a variable as final is essentially making it read-only; however, you can still set a final value to the value of a variable. (This is different from constants, where the value of constants must be known at compile time so constants may only be set equal to other constants.)

Using base class members and base constructors
The keyword this works the same in Java and C#. In Java the super reference variable is used to signify the immediate parent class. In C# the equivalent is base. Take a C# class CalculateFor that provides the ability to work out the value of integer x raised to a particular integer power (for example, x raised to the power of three is x multiplied by x multiplied by x), given x and the power (provided an overflow does not occur):

using System;
public class CalculateFor
{
internal int x;
public CalculateFor(int x)
{
this.x = x;
}
public int ToThePower(int power)
{
int total = 1;
for(int i = 0; i < mynumber =" new" result =" myNumber.ToThePower(3);" y =" y;" total =" 1;" i =" 0;" total =" (base.x).(base.ToThePower(power));">Method overriding and hiding
In C#, method overriding is a very explicit procedure. This is quite different from the Java approach, where overriding is the default behavior when the signature of a super class member is the same as the signature of its subclass. In C#, to provide method overriding functionality, the modifiers virtual and override are used in tandem. All methods in the base class that you expect will be overridden must use

C# for Java Developers
the virtual keyword. To actually override them use the override keyword in the child class. The following code uses an example class and subclass to demonstrate the override functionality:

using System;
public class FruitPlant
{
public FruitPlant(){}
public virtual void BearFruit()
{
Console.WriteLine(“Generic fruit plant”);
}
}
class MangoTree : FruitPlant
{
public MangoTree(){}
public MangoTree(){}
public override void BearFruit()
{
Console.WriteLine(“Tree fruit is:->Mango”);
}
}
public class FruitPlantTest
{
public FruitPlantTest(){}
public static void Main(string[] args)
{
FruitPlant p = new FruitPlant();
p.BearFruit();
MangoTree t = new MangoTree();
t.BearFruit();
((FruitPlant)t).BearFruit();
}
}
Compiling and running this code produces the following output:
Generic fruit plant
Tree fruit is:->Mango
Tree fruit is:->Mango
As you can see the most derived Fruit() method is called, irrespective of our use of final cast of the MangoTree instance to the Plant instance. Indeed, the benefit of using method overriding is that you are guaranteed that the most derived method will always be called.
Although we cannot override a method in C# unless the method was originally declared as virtual, C# also introduces a new concept, method hiding. This allows developers to redefine super-class members in the child class and hide the base class implementation even if the base member is not declared virtual. C# uses the new modifier to accomplish this.


The benefit of hiding members from the base class rather than overriding them is that you can selectively determine which implementation to use. By modifying the previous code we can see this concept in action:

public class FruitPlant
{
public FruitPlant(){}
public void BearFruit()
{
Console.WriteLine(“Generic fruit plant”);
}
}
class MangoTree : FruitPlant
{
public MangoTree(){}
new public void BearFruit()
{
Console.WriteLine(“Tree fruit is:->Mango”);
}
}
// then FruitPlantTest implementation
Running this example produces this output:
Generic plant fruit
Tree fruit is:->Mango
Generic plant fruit
In other words, unlike overriding, when hiding methods, the method invoked depends on the object the method is called on. For the last line of output, we cast the MangoTree instance back to a Plant instance before calling the BearFruit() method. So the Plant class’s method is called.
You should note that the new modifier can also be used to hide any other type of inherited members from base class members of a similar signature.
Input and Output
Being able to collect input from the command prompt and display output in the command console is an integral part of Java’s input/output functionality. Usually in Java one would have to create an instance of a java.io.BufferedReader object, using the System.in field in order to retrieve an input from the command prompt. The following code shows a simple Java class, JavaEcho, which takes input from the console and echoes it back, to illustrate the use of the Java.io package to gather and format input and
output:

import java.io.*;
public class JavaEcho {
public static void main(String[] args)throws IOException {
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
String userInput = stdin.readLine ();
System.out.println (“You said: “ + userInput);
}
}

C# for Java Developers
In C#, the System.Console class provides methods that can provide similar functionality for reading and writing from and to the command prompt. There is no need for any extra objects; the Console class provides methods that can read entire lines, read character by character, and even expose the underlying stream being read from. The members of Console are briefly described in the following tables.
Public Properties Description Error Gets the system’s standard error output stream as a TextWriter object. In Gets the system’s standard input stream as a TextReader object.
Out Gets the system’s standard output stream as a TextWriter object.
Public Methods Description

OpenStandardError() Overloaded. Returns the standard error stream as a Stream object.
OpenStandardInput() Overloaded. Returns the standard input stream as a Stream object.
OpenStandardOutput() Overloaded. Returns the standard output stream as a Stream
object.

Read() Reads the next character from the standard input stream.
ReadLine() Reads the next line of characters as a string from Console, which
is set to the system’s standard input stream by default.
SetError() Redirects the Error property to use the specified TextWriter
stream. SetIn() Redirects the In property to use the specified TextReader stream.
SetOut() Redirects the Out property to use the specified TextWriter
stream. Write() Overloaded. Writes the specified information to Console.Out.
WriteLine() Overloaded. Writes information followed by a line terminator to
Console.Out. All of the Console members are static, so you don’t need to (and can’t) instantiate a System.Console.object. Using the powerful methods of the Console class we could write an equivalent of the JavaEcho class in C# as follows:

class CSEchoer
{
static void Main(string[] args)
{
string userInput = System.Console.ReadLine();
System.Console.WriteLine (“You said : “ + userInput);
}
}

The previous code is much shorter and easier to digest in comparison to its Java counterpart. One useful thing you’ll get with the Console.WriteLine() static method is the ability to use formatted strings. The flexibility of formatted strings can be illustrated by writing a simple game where user input is used to generate a story. Here is the code for this game, EchoGame:

class EchoGame
{
static void Main(string[] args)
{
System.Console.WriteLine(“Name of a country?”);
string userInput1 = System.Console.ReadLine();
System.Console.WriteLine(“Name of a young prince?”);
string userInput2 = System.Console.ReadLine();
System.Console.WriteLine(“What was the prince doing?”);
string userInput3 = System.Console.ReadLine();
System.Console.WriteLine(“What did he find while doing this?”);
string userInput4 = System.Console.ReadLine();
System.Console.WriteLine(“Then what did he do?”);
string userInput5 = System.Console.ReadLine();
System.Console.WriteLine(“Once upon a time in”
+ “ {0}, there was a young prince {1},\n” +
“who while {2}, came across a {3}, and then “
+ “{4} ! “, userInput1, userInput2,
userInput3, userInput4, userInput5 );
}
}
The insertion points are replaced by the supplied arguments starting from the index {0}, which corresponds to the leftmost variable (in this case userInput1). You are not limited to supplying only string variables, nor are you confined to using just variables, or even using variables of the same type. Any type that the method WriteLine() can display can be supplied as an argument, including string literals or actual values. There is also no limit to the number of insertion points that can be added to the string, as long as it is less than the overall number of arguments. Note that omitting insertion points from the string will cause the variable not to be displayed. You must, however, have an argument for each insertion point you specify whose index in the argument list corresponds to the index of the insertion point. In the following listing, for example, removing {1} is fine as long as there are still three arguments. In
this case {0} matches up with strA and {2} matches up with strC:
Console.WriteLine(“hello {0} {1} {2}”, strA, strB, strC);

Summary
Microsoft describes C# as a simple, modern language derived from C and C++. Because Java is also a modernization of C++, much of the syntax and inbuilt features present in C# are also available in Java. C# uses.NET Framework, and so offers built-in, type-safe, object-oriented code that is interoperable with any language that supports the Common Type System (CTS). Java does offer interoperability with C and
C++, but it is not type-safe. Moreover, it is highly complex.

C# namespaces provide a much more flexible way of grouping related classes. C# filenames are not bound to the classes within them as they are in Java, nor are namespace names bound to folders as package names are in Java. C# also provides a rich set of built-in value types, including type-safe enumerations, structures, and the built-in primitives that offer a robust alternative to Java’s primitives. C# provides bi-directional conversion between reference and value types called boxing and unboxing. This functionality is not supported in Java. C# supports the use of classes, complete with fields, constructors,
and methods, as a template for describing types, and provides the ability to define destructors,
methods called just before the class is garbage collected. C# also provides three approaches to method parameters—in (default), out, or ref. C# also introduces the concept of method hiding, as well as supporting explicit overriding with the virtual and override keywords, and C# providesproperties as an alternative to get() and set()methods as a way to access safely internal fields.

No comments: