AddThis Social Bookmark Button

Print

Contrasting C# and Java Syntax
Pages: 1, 2, 3

Conditionals

The two conditional structures that Java programmers expect, the "if-then-else" and "switch" statements, are both available in C#. Both behave similarly except for one subtle difference in the C# "switch" statement syntax.



Java allows for control flow to implicitly fall between different cases in the switch statement, whereas the C# compiler explicitly does not allow this -- the C# compiler will mark this as a syntactical error. For example, in Java the following is legal:

int switching = 3;
switch( switching ) {
case 3:
  System.out.println( "here" );
default:              
  System.out.println( "and here" );

}

This will result in both printlns being executed. In C#, an explicit break or goto case to a different case is required somewhere in the case to explicitly define the control flow.

Loops

C# has the familiar "while," "do-while," and "for" loops. On top of these three, C# has introduced a "foreach" loop that operates on objects that implement the System.Collections.IEnumerable interface. Most notably, arrays in C# (System.Array) implements IEnumerable, so the following Java code

int[] array = // something...
for( int count=0;count<array.length;count++ ) 
  System.out.println( array[count] );

is legal in C#, but it can also be represented in C# as

foreach( int member in array )
  Console.WriteLine( member );

Specifically, the IEnumerable interface provides the ability to get an IEnumerator representation to an object (similar to java.util.Enumeration). Anything which implements the IEnumerable and IEnumerator interfaces can be operated on by the "foreach" loop.

Jumps

Most of the Java jump statements map into C#: break, continue, goto, and return. These statements are used the same way they are used in Java: to break out of loops or to return control to a different block.

What deserves a discussion is the exception model, as it differs both semantically and syntactically. As mentioned in my previous article, all exceptions in C# are run-time exceptions; the compiler is not going to help the programmer keep track of exceptional situations. It should also be noted that method signatures do not contain the exception that can be thrown inside the block. My warning to Java programmers turned C# programmers: be very careful.

The "try-catch-finally" block that Java programmers are familiar with exists in C#, and so do a few additional syntactic sugars. All exceptions derive from System.Exception, so catching System.Exception will catch all possible exceptions thrown in a block, just like in Java. A shortcut is available if the exception object is not needed by using the following framework:

try {
  // something that may thrown an exception   

} catch {
  // deal with the exception without getting a handle
  // to the exception object

}

But if you do need to catch a specific exception (while again not requiring the exception object), try something like

try {
   
} catch( IOException ) {

}
Table 2: Useful properties of Exceptions in Java and C# Exception messages and exception stack traces are usually needed by programmers and logs
Java C#
getMessage() Message
printStackTrace() StackTrace (this is not exactly equivalent as printStackTrace and its Java related method prints the stack trace to a stream, whereas StackTrace returns a C# string)

Methods

Methods act just as we would expect them to behave. At the basic level there are no differences between C# and Java methods; each method takes parameters, and has a return type.

class A {
  public void MethodA1() { }

  public int MethodA2() { }
  public void MethodA3( int i ) { }
  public int MethodA4{ int i ) { }

}

As we believe it should, this creates a class A that has one method named MethodA1 that does not take any parameters and does not return any value. MethodA2 returns an integer, MethodA3 takes an integer as a parameter, and MethodA3 both returns an integer and takes an integer as a parameter.

But also as we expect, C# has a few more things that we can do with methods that we could not do before in Java.

params

When calling a method, the Java compiler checks that there is a method that matches its signature. For example, in Java, if there is a method defined as

public void methodCaller( int a, int b, int c );

then a call of that method

methodCaller( 3, 4, 5, 6 );

will generate a compiler error as the Java compiler cannot find a method named methodCaller that takes four ints. We cannot create a method signature that allows us to take a variable number of ints as parameters.

Why should this even matter? If a programmer wants to take a variable number of ints, he can define a method signature that takes an array of integers and then construct the array when calling the method. In Java, this will take at least three lines of code just to call the method -- the first to create the array, one or more lines to assign values into the array, and the third to call the method. C# attacks this issue by allowing programmers to place a params modifer on the last array parameter of the method, so that a variable number of parameters can be passed into it. Using the above example, the method signature can be defined as

public void methodCaller( params int[] a );

and the method can be called with any of

methodCaller( 1 );
methodCaller( 1, 2, 3, 4, 5 );

Inside methodCaller, the parameters can be accessed through the "a" array defined.

ref and out

C# can also force a parameter to be passed in by reference as opposed to being passed by value. Taking a primitive type, for example

public void increment( int a ) {
  a++;

}

int a = 3;
increment( a );
// a still == 3

will not cause the variable passed into increment to actually be incremented because a is being passed in by value; the variable a in the increment block is in a different environment, and therefore changes in that scope do not propagate back out.

However, changing the method to

public void increment( ref int a ) {

  a++;

}

int a = 3;
increment( ref a );
// a now == 4

will cause the int a to be passed in by reference (just as classes are passed in) and therefore modifying it will cause the original value to be changed. Using ref with a class allows a function to reassign the class pointer inside the function and have that change propagate outside the method.

A natural partner to ref is the out keyword. While ref does not guarantee that any operations will actually be performed on the variable, using out will cause the compiler to make sure that a value has been set to the variable. Code such as

public void DoNothing( out int a ) { }

will cause the compiler to complain as a is not assigned to anything.

Pages: 1, 2, 3

Next Pagearrow