Sunday, February 06, 2005

My review of C#

I finally finished learning a thing or two about C#. My original intent was expanding my knowledge of the .NET world. I used Mono and was able to make my way through an entire book about C#. The book didn't delve too far into the frameworks and concentrated mostly on the language. Following are the notes I took while working my way through the book. They're written from a Java developer's perspective (with the odd smattering of Delphi and ObjC thrown in for good measure). Next I'll probably look into things like nant, nhibernaate, and nunit, the C# equivalents of tools I commonly use in the Java world...

Overall I was pretty happy with C# as a language. It's very much like Java and the comments below only reflect the things that are different. Generally, I would say C# is a legal J++ (Microsoft's slightly mutated Java that was taken off the market after Sun sued and won). I originally thought J++ was pretty good and I think the same about C#.

Namespaces and File structure
  • Many namespaces in one file.

  • No tie between public class names and name of file or name of namespaces (packages in Java) and the directories they live in. Simpler.

  • But by convention one class or a few highly related classes are grouped in individual files, so in practice it may not be much different

Ref and Out parameters
  • ref and out parameters must be marked in the method declaration and on the calling side. Good for readability.

  • vars to be used as a ref param must be assigned before calling method.

Misc
  • Main is the name of the entry point method (one per file). Note the capital M. C# uses PascalCase vs camelCase for most names. This is a bit unusual for Java developers but makes sense once you realize Anders Hejlsberg, the primary designer of C# and .NET, was the chief architect of Delphi at Borland which used Object Pascal.

  • string is an intrisic type in C# (see more about structs later)

  • Parameter substitution in Console.WriteLine() is useful. There is also an ability to format the parameters (e.g., Console.WriteLine( "Sum of 1,2,3 is {0:N0}.", Sum(1,2,3));) Presumably there'd be a way to generate stings using this formatting functionality. I haven't run into it yet.

  • "public sealed class Plane:Flyer" sealed stops any subclasses like final in Java

  • Use colon (:) for subclassing instead of extends

  • Use colon (:) for implementing an interface instead of implements

  • Visibility identifiers are nearly the same, public, protected, private, internal. Internal is like package scope in Java. Default is private in C# as opposed to protected in Java when it isn't explicitly defined.

  • Exception handling is the same as Java except there are no checked exceptions in C#

  • Use "is" instead of "instanceof"

  • Interfaces are available in C#, like the IComparable with the int CompareTo( object o) method. Naming convention starts interfaces with I.

Inheritance

  • In Java, every method is virtual and every method call is dispatched with a dynamic lookup. In C# you must explicitly label a method as being virtual. This has the potential to create some unexpected behavior:

    1. Create a subclass and override a method using syntax like "new public void MethodName()"

    2. Create a variable declared to be the supertype.

    3. Assign this variable an instance of the subclass.

    4. Now call the overridden method.

    5. The method that gets called will actually be that of the super class and NOT the subclass.

    6. If you were to typecast it to the subclass then the subclass's method gets called. Funky.

    7. This doesn't happen if the super's method is declared virtual and the subclass is declared with override

  • You must explicitly label an overriden method with the keywords override or new. Compiler will fail otherwise.

  • Multiple constructors are supported but in order to call other constructors in the same class you have to use a strange declaration. (e.g., public Employee(): this(null, 0){...}) So why is't "this(null,0)" between the braces?

  • To call a super class's constructor use something like "public Manager():base("Joe", 100){...}".

Properties
  • In Java an instance variable with get and set methods is oftern referred to as a property. This idiom is often used by IDE's.

  • C# defines a special syntax for properties that reduces some of the code that needs to be written. Basically it comes down to declaring a private instance variable usually named with camelCase (one of the few exceptions). Then you define a property with get and set blocks:


private string name;
public string Name{
get{ return name; }
set{ name = value; }
}

  • Now the property can be referenced just like an instance variable but behind the scenes the get and set blocks of the property is being called. I think this is a much more natural syntax than calling a method. e.g.,

person.Name = "Joe";

  • Delphi had all these features too (with a different and IMHO simpler syntax). I was also suprised that I didn't see any way to simply declare indexed properties. Delphi had that one too.

Compiler
  • Mono mimics the Microsoft C# command line compiler very well:

  • multiple files compiled at once to create the exe "mcs /out:Test.exe Ape.cs Human.cs"

  • to compile just this class and create a *.netmodule file: "mcs /target:module Ape.cs"

  • to compile the exe with the *.netmodule use: "mcs /out:Test.exe Human.cs /addmodule:Ape.netmodule"

Structs
  • Supposedly a struct differs from a class by the way the memory is allocated.

  • Structs are created more like intrinsic variables within the class

  • But they look just like classes! They can implement interfaces, their members have visibility specifiers, and they can even have methods and constructors!

  • boxing and unboxing happen automatically between intrinsics and their structure brethren. e,g, int and Int32 (a struct)

  • The is operator also works on structs

Delegates
  • They're similar to function pointers and similar to Objective-C's selector concept (although objc's selector is more dynamic in that it's a message that isn't tied to any particular object instance).

  • To use delegates:

    1. declare the delegate that describes a method signature

    2. instantiate a delegate that points to the method of an object instance that has a matching method (note that the method name doesn't matter just the return type and parameter types) e.g., MessageDelegate target = new MessageDelegate( myObject.PrintSomethingOut );

    3. now invoke the method e.g., target("Hello, World!");

  • This all avoids the mess in Swing where you must create a Listener Interface, often a Listener Adapter and then implement the interface or subclass the adater with an anonymous class. For example when wiring up gui object events to methods:


button.addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e ){
//do Something like delegating to another method
}
});

  • Five lines of code vs one plus all the overhead of a new class just to delegate a method call!! Now the Java version is closer to the typical Observer pattern and is pretty well understood and is still valid but I must admit that I like the brevity and readability of the delegate implementation.

Collections
  • Collection types are LinkedList, ArrayList, Queue, Stack, Dictionary which are similar to Java's List, Map, and Set interfaces and the various implementations.

  • I like names like Queue, Stack, and Dictionary

  • Index access to the collection

Console.WriteLine(((Address)emp.Addresses[1]).City);

  • this is actually calling the get method of the class with an index value, the index doesn't have to be an int. e.g.,


class MyArray{
public String this[index]{
get{ return array[index];}
set{array[index] = value;}
}
}

  • C# uses the term IEnumerator. Enumerator was deprecated in Java in favor of the Iterator interface. but basically the same thing

  • If the class implements IEnumerable then the foreach loop can be used instead which does the typecasting automatically on each loop iteration.

No comments: