Android to WP7-Chapter 4: C# programming

Date: Friday, June 3, 2011, 10:47:39 AM

Tags:

Table of Contents

In the previous chapter, we looked at the user interface guidelines for WP7 applications. We will now dive deeper into what it takes to implement a WP7 application.

In this chapter, we will look at the various C# features that map to the most common Java features. We will provide code snippets which will ease the transition into C# code. We will point to the key C# features that help you write safe code and enhance productivity.

Managed Programming

WP7 uses the .NET environment to develop applications using managed programming in C# or VB.NET. Before we jump into the details of C#, let us briefly review the .NET programming environment.

clip_image002

The C# compiler (and similarly, the VB compiler) compiles the C# (or VB.NET) code in an intermediate language (IL) byte code and metadata. The Common Language Runtime (CLR) executes the byte code. C# uses metadata to manage type safety, exception handling, and array bounds checking etc. The CLR also manages memory and performs garbage collection. This is similar to Android where the Java code is compiled into a .dex file which is then executed by the Dalvik VM.

;

A Comparison between C# Features and Java Classes

Class Declaration

Like Java, C# does not separate class definition from class implementation. The compiler derives the metadata about the class from the class implementation. As in Java, we can define multiple class definitions in the same file. C# also defines multiple classes in the same file. However, unlike Java, more than one class in a file can be public and the name of the file may be different from the public class in the file.

In the example, the public signature of the class Person consists of the age property and the constructor. The rest of the class implementation is opaque.

using System;                 // In java this is similar to import
namespace FirstApplication    // scope for classes.  Similar to package declaration in Java
{
class Person            // only uses class implementation. 
{
        private DateTime birthDate;      // a private field accessible to this class
        private int ageOn(DateTime date) // a private method
        {
            TimeSpan span = date.Subtract(birthDate);  //uses a .notation to invoke
            return span.Days;
        }
        public int age                   // this is a property. Unlike Java, C# has properties 
        {
            Get                          // just a getter; it's a read-only property
            {
                return this.ageOn(DateTime.Now); 
              }
        }
        
public Person( DateTime dob)  // instance constructor. Similar to Java
        {                // it combines allocation and initialization
            birthDate = dob;
           } 
}
class Program                        // Unlike Java, more than one class in the same file can be public. 
{
     static void Main(string[] args) // main entry point into the program
     {
         Person p = new Person(new DateTime(1973,11,12));  //construct an instance
         System.Console.WriteLine("The age is  is" + p.age.ToString()); 
         DateTime dt = p.birthDate;  //error in compilation birthDate is private    
        }
    }
}

Instead of using the import statement in Java, C# employs a using statement to refer to the metadata of other classes. The namespace declaration that is shown at the top of the file is used to declare the scope and to organize the code. You can access a class in another namespace by referring to its fully-qualified name. See the reference to System.Console.WriteLine in the example above, where console is in the System namespace.

Strong Typing

C# is a strongly typed language like Java. The types must be specified for variables and input/output parameters. The compiler enforces the types. In the section on generics, you can see how C# uses strong typing for collection classes.

Strong typing works similarly for all classes. The code example below shows the strong typing for primitive types.

int a = 5;              
int b = a + 2; //OK  
bool test = true; // OK
int c = a + test; // Error. Operator '+' cannot mix type 'int' and 'bool'.

Class Constructors

Like Java, C# uses instance constructors to create and initialize instances. For example: p is an instance of the Person class. You can construct and initialize p with a given birthdate, in a single statement.

Person p = new Person(new DateTime(1973,11,12));

Properties

Unlike Java which has no class properties, C# classes can have properties. The properties can be defined as read-only, write-only or read-write. Properties provide a natural syntax for accessing properties. You often need to decide whether to implement a member as a property or a method. As a general rule, use properties when you need to access data. To take any action on the data, use methods.

Properties help to abstract away from directly accessing the members of a class. This technique is similar to using accessors (getters) and modifiers (setters) in Java. You can make the C# property read-only by providing the getter, write-only by providing the setter, or read-write by providing both getter and setter.

Parameter Types

Like Java, C# uses value parameters by default. Parameters that are passed by value cannot be modified in the method. But unlike Java, C# also allows the passing of parameters by using the ref modifier. You can pass parameters by ref where you want to change the value of the actual parameter. In some cases, you need to use the reference parameters for better efficiency since they avoid data copying.

void Foo (ref int x, int y)
{
    x = 0;
    y = 0;
}
..
int a = 5;
int b = 8;
Foo (ref a, b);
//a is zero and b is still 8

C# also provides the parameters with an out modifier. The out modifier represents the parameters that must be initialized by the called method before returning. This design pattern is often used to return the error in addition to the value of the function.

Access Privileges

Like Java, C# allows access privileges on fields (for example, birthDate), properties (for example, age) and methods (for example, ageOn). C# uses public, private, and protected as modifiers to denote the three different levels of access privileges.

In the above example, the compiler gives an error on p.birthDate since that variable is private. Therefore, p.birthDate is not accessible from the Program class. Similarly, the ageOn method is also private and inaccessible from the Program class.

Methods with Multiple Parameters

Both Java and C# support methods with multiple parameters. While C# traditionally uses positional and unnamed parameters, the latest version of C# also includes named parameters. The following example shows the comparative syntax for Java and C#.

image

Like Java, C# explicitly supports method overloading. Both Java and C# use method name and parameter types for defining method signatures and for differentiating between methods. The following code sample shows how C# differentiates between methods that have the same name.

void insert (myClass obj, int index);
void insert (myClass obj, myClass before);

The method insert may be called with both these signatures:

list.insert (myObj1, 4);
list.insert (myClass obj, myClass before);

The following code sample shows another example of method overloading:

using System;
namespace SecondApplication
{
    struct Point                            // In contrast to Java C# provides structs 
    {                                       
        public double x;                    // struct fields can also have access modifiers
        public double y;
        public Point(double p1, double p2)  //a constructor for the struct
        {
            x = p1;
            y = p2;
        }
    }
    interface IThreeDShape                  // an interface, like a Java interface
    {                                       // defines the behavior
        double volume   
        {
            get;                            // Volume is a read-only property. no setter
        }
    }
    abstract class Shape                    // this class is marked abstract, i.e. may not be instantiated.
    {
        protected Point origin;             //only derived classes may access  
        protected static int counter = 0;   // Similar to protected variables in Java
        public string ID;                   
        protected Shape()                   //a constructor. Same name as the class name
{
            counter++;                      // class variable being updated
        }
        public Point Origin                 // similar to Java class
variables 
        {
            set
            {
                origin = value;
            }
        }
        public abstract double Area         //denotes that this property must be overridden
        {                                   // in a derived class
            get;                           
        }
        public abstract bool contains(Point p);  // this method must also be overridden
    }

    class Rectangle : Shape                 //Similar to Java 'extends'
    {
        public double length;               //field accessible from others
        public double width;
        public Rectangle(Point o, double l, double w)   //a public constructor
   {
            ID = "Rectangle_" + counter.ToString();
            origin = o;
            length = l; width = w;
        }
        public Rectangle(double l, double w)  // one constructor using another constructor 
//creates a rectangle at the origin
            : this(new Point(0, 0), l, w)
        {
        }
        public override double Area         // Subclass must implement abstract methods of parent class
    // unlike Java, overridden method must
        {                                   // use override keyword
            get
            {
                return length * width;
            }
        }
        public override bool contains(Point p)
        {
            if ((origin.x < p.x && origin.x + length > p.x) || (origin.x > p.x && origin.x - length < p.x))
                if ((origin.y < p.y && origin.y + length > p.y) || (origin.y > p.y && origin.y - length < p.y))
                    return true;
            return false;
        }
    }
    class Square : Rectangle
    {
        public double side;
        public Square(double s)
            : base(s, s)  //constructor
        {
            ID = "Square_" + counter.ToString();
            side = s;
        }
    }
class Cube : Shape, IThreeDShape          //similar to Java, class implements interface 
    {
        public double side;
        public Cube(double s)
        {
            ID = "Cube_" + counter.ToString();
            side = s;
        }
        public override double Area
        {
            get
            {
                return 6 * side * side;
            }
        }
        public double volume
        {
            get
            {
                return side * side * side;
            }
        }
        public override bool contains(Point p)
    …
    }
    class SecondProgram
    {
        static void printVolume(IThreeDShape tdShape)
        {
            Console.WriteLine("The volume is " + tdShape.volume);
        }
        }
   static void Main(string[] args)
        {
            Rectangle r = new Rectangle(5.0, 3.0);
            Cube c = new Cube(4.0);
            SecondProgram.printVolume(c);
            double a = r.Area;
            Console.WriteLine("The area of rectangle " + r.ID + " is " + a.ToString());
            bool b = r.contains(new Point(1, 2));
            Console.WriteLine("The point is in " + b.ToString());    // will print TRUE     
        }
    }
}

Inheritance

Like Java, C# uses a single inheritance mechanism. Inheritance is specified by listing the parent class after the class name as shown below. In this example, the class Rectangle inherits from the class Shape, and the class Square inherits from the class Rectangle.

class Rectangle : Shape
class Square : Rectangle

Similar to Java, in C#, the no parameter constructor of the base class is automatically invoked when you construct an instance of a derived class. Similarly, a derived class in C# can invoke a specific constructor of the base class if needed. You can see this in the constructor of the Square class.

public Square(double s): base(s, s) //constructor. Calls parent constructor explicitly

Unlike Java, a C# derived class may not override a method by redefining it. The class must use the keyword override in its method definition to override the definition in the parent class.

public override bool contains(Point p)
{
    …
}

Protected Access

Like Java, in C#, you can use the protected modifier to limit access to fields, properties, and methods. Protected members are accessible only to derived classes. You can implement protected variables in C# by using the protected access modifier, as shown in the code sample below:

protected Point origin;
protected static int counter=0;

Instance vs. Class Level Access

Like Java, C# uses a static modifier to denote class level methods, fields, and properties. Other members without static modifier are at an instance level. In the above code example, counter is a class level variable.

protected static int counter=0;

Abstract Classes

The abstract classes in C# are similar to Java abstract classes that they cannot be instantiated. The class Shape defined in the above C# code sample is an abstract class. The abstract classes requires that both Area property and contains method must have an override in any derived classes.

abstract class Shape
{
    public abstract double Area
    {
        get;
    }

    public abstract bool contains(Point p);
}

Interfaces

Java and the C# interfaces are similar. In the sample code shown below, Interface IThreeDShape is implemented by the Cube class. In both languages Interface defines a contract consisting of method signatures, but no implementations. A class that implements an interface must implement all methods defied in the interface.

interface IThreeDShape
  {
    double volume
    {
       ...
    class Cube : Shape, IThreeDShape

Polymorphism

Polymorphism is the same in both Java and C#. You can pass a C# derived class as a parameter to a method that expects a base class. Similarly, if a method expects an interface parameter, you can pass an instance of a class that implements that interface. The following sample code shows how to pass an instance of the class Cube as a parameter, where the method expects an object of the class IThreeDShape.

static void printVolume(IThreeDShape tdShape)
  {
    Console.WriteLine("The volume is " + tdShape.volume);
  }
    …
  Cube c = new Cube(4.0);
  SecondProgram.printVolume(c);

Structs

Unlike Java, C# provides structs as first class language primitives. Structs are similar to classes except that they are a value-type. Additionally, a struct does not inherit from a class or struct nor can other classes inherit from it. C# structs can use modifiers and can have constructors, methods, and properties.

struct Point
   {
    public double x;
    public double y;

;

Object Lifecycle: Creation and Deletion of Objects

Both Java and C# performs automatic memory management. Both languages use the new operator to create objects, class instances, and initialize them. When the code execution reaches a place where an object is outside the scope, i.e. it can no longer be accessed, the object becomes eligible for garbage collection. In C#, the garbage collection is implemented using .NET. The .NET CLR garbage collector periodically frees up the memory for the objects that are no longer accessible. With C#, you don't have to track the free memory usage.

In rare circumstances, you may need to perform a cleanup at the time that an object is destroyed. C# allows the use of destructors, which are similar to Java finalizers, but in practice this is rare.

Type Checking vs. Reflection

Reflection is the ability to discover the members of a class and to invoke methods at runtime. Both Java and C# support reflection. You can use reflection to:

  • Get information type from an existing object.
  • Dynamically create an instance of a type.
  • Bind the type to an existing object, access its methods, and access its fields and properties.

The following table maps the dynamic type checking in Java with its corresponding C# reflection features.

image

Exception Handling

C# and Java exceptions have many similarities. They use very similar syntax for declaring exceptions; try blocks delineate guarded regions, catch blocks handle exceptions and finally blocks release any resources. Exceptions can be caught and re-thrown. You can either catch specific exceptions or use a catch-all statement.

Unlike Java, C# does not have checked exceptions. In C#, all exceptions are unchecked and there is no counterpart to the throws declaration for the method signature.

try
    {
        //block of code
      }
    //Most specific:
    catch (ArgumentNullException e)
    {
        Console.WriteLine("{0}First exception caught.", e);
    }
    //Least specific
    catch (Exception e)
    {
        Console.WriteLine("{0}First exception caught.", e);
    }

A Comparison of Important Class Libraries

Strings

C# provides a comprehensive string class, which offers you all the features that you associate with this class.

image

;

Arrays

Arrays in C# are almost like arrays in Java. Both support jagged arrays, i.e., arrays of arrays. In addition, C# also supports multi-dimensional arrays which are rectangular.

image

Dictionaries

C# provides a generic dictionary class that is similar to the HashMap functionality in Java. The generic dictionary class allows you to add, lookup, and remove objects from the dictionary. Since the dictionary class uses Generics, it also utilizes strong typing.

image

Generics

Both Java and C# support generics. Generics introduce the notion of type parameters that make it possible to design classes that are type safe, even though the actual type is deferred till the object's instantiation. Java implements generics using erasure, i.e. type information is used only at compile time and not at runtime. This introduces certain limitations in Java generics.

C#, on the other hand, implements generics using explicit support in .NET CLR. The generated intermediate language (IL) supports the notion of types.

The following code shows how to define a generic stack:

Stack<int> intStack = new Stack<int>();         // intStack is a stack of int 
intStack.Push(1);                               // OK
intStack.Push(2);                               // OK
int number = intStack.Pop();                    // this is a type safe assignment
Stack<string> strStack = new Stack<string>();   //the type of strStack is different from type of intStack
strStack.Push("green");                         // OK
strStack.Push(23);

The Stack<T> uses T as a type parameter, thus allowing you to instantiate a stack of any type. For example: Stack<int> or Stack<string>. You can use them in a type safe manner.

Operator Overloading

Operator overloading allows you to define the implementation of user-defined operators for user-defined classes. Use of operators can often improve the readability of the program. Consider the following example of a complex number struct. Operator Overloading allows you to define a + operation by using a natural syntax.

Operator overloading is not supported in Java.

public struct Complex 
    {
        public int real;
        public int imaginary;
        // Declare which operator to overload (+), define how it is computed
        public static Complex operator +(Complex c1, Complex c2) 
        {
            return new Complex(c1.real + c2.real, c1.imaginary + c2.imaginary);
        }
     …
    Complex c1 = new Complex(3.0, 4.0);
    Complex c2 = new Complex(4.0, 5.0);
    Complex cSum = c1 + c2;

Delegates

There is no concept of delegates in Java. The functionality of delegates in C# is like the function pointers in C. However, unlike function pointers, C# delegates are strongly typed and also improve program readability.

In this design pattern, a class delegates another method with the same signature as the delegate even though the actual method is not known at compile time.

using System;
namespace DelegateExample
{
    public class ConsoleLogger
    {
        public static void WriteString(string s)
        {
            Console.WriteLine("Writing to console log: {0}", s);
        }
    }
    public class FileLogger
    {
        public static void LogString(string s)
  {
            Console.WriteLine("Logging to file log: {0}", s);
        }
    }
public class DelegatesTest
    {
        public delegate void StringDelegate(string s);
        public static void Main()
        {
            StringDelegate Writer, Logger;             // define twp StringDelegate objects
         Writer = new StringDelegate(ConsoleLogger.WriteString); // Create delegates with appropriate methods
            Logger = new StringDelegate(FileLogger.LogString);
            Writer("Warning message 1\n");             // Send to Console Writer delegate method
            Logger("Warning message 2\n");             // Send to File Logger delegate method
            StringDelegate MultiLogger;                // to act as the multicast delegate
            MultiLogger = Writer + Logger;             // combine the two delegates, 
            MultiLogger("Warning message 3");          // This should get sent to both delegates
        }
    }
}

In the above code example, StringDelegate is defined as a function that takes a string as a parameter and returns void. Writer, logger, and multiLogger are constructed by passing methods that have the same signature as the StringDelegate declaration.

Calling Writer invokes the writeString method of ConsoleLogger to print the message to the console. Calling Logger invokes the logString method of FileLogger to log the message to the file. Delegates achieve indirection while providing type safety. Delegates may be concatenated as shown by MultiLogger, which logs the message to both loggers.

Such a design pattern can only be implemented using reflection in Java. However it does not provide the type safety that delegates provide.

Events

Both Java and C# support event handling though there are significant differences. There is no general mechanism for events in Java though specific design patterns and classes may be used for events.

Events are useful in the pub-sub (publisher and subscriber) design pattern and are useful for asynchronous programming. C# events are implemented using delegates. In C#, the event is used to automatically specify that a field within a subscriber is a delegate that will be used as a callback during an event-driven situation. An object can publish an event that a subscriber can subscribe to. When the publisher raises an event, all subscribers are notified without publisher knowing who the listeners are.

using System;
namespace DelegateExample
{
    public class ConsoleLogger
    {
        public  void WriteString(string s)
        {
            Console.WriteLine("Writing to console log: {0}", s);
        }
    }
    public class FileLogger
    {
        public  void LogString(string s)
        {
            Console.WriteLine("Logging to file log: {0}", s);
        }
    }
    public class DelegatesTest
    {
        public delegate void LogEventHandler(string s);             // definition of the delegate.
        public static event LogEventHandler logEvent;               // the signature of the event. 
        public static void Main()
        {
            ConsoleLogger cl = new ConsoleLogger();                 // create the first subscriber
            FileLogger fl = new FileLogger();                       // the second subscribe

            logEvent += new LogEventHandler(cl.WriteString);        // subscribe the event and hook up the     
            logEvent += new LogEventHandler(fl.LogString);          // event handlers
            logEvent("A new event");                                // raise event which will invoke handlers
            Console.ReadLine();
        }
    }
}

;

Comparing API Documentation Tools

JDK contains an API documentation generation tool called Javadoc. Javadoc automatically generates documentation from the comments that are added to the java source code file.

There are a variety of document generation tools that are available for .NET, namely,

NDoc, Sandcastle, Doxygen, Doc-O-Matic.

In comparison to Javadoc which produces HTML documentation, NDoc can generate documentation in several formats, including:

  • MSDN style HTML Help format (.chm)
  • Visual Studio .NET Help format (HTML Help 2)
  • MSDN online style web pages

Unlike Java doc comments which are written in HTML, C# doc comments use XML as shown below.

public class MyClass() {
///<summary>
///
///</summary> 
///<param name="s"></param>
Public MyClass(string s) {}
  }

Summary

In this chapter, we looked at C# programming from the perspective of a Java developer. Java and C# have many similarities and yet have some subtle differences. The knowledge of Java and object oriented programming will help you master C# quickly.

Related Resources

To go deeper into C# and Java, visit:

To go deeper into NDocs, visit:

 
blog comments powered by Disqus