Transcription

Dr Dobbs Journal: C# Versus Java (Feb 2001)C# Versus JavaDr. Dobb's Journal February 2001Do we really need another language?By Marc EaddyMarc is a project leader developing real-time stock market applications at ILX Systems. He can becontacted at [email protected] columbia.edu.Microsoft describes C# ("C sharp") as a "simple, modern, object-oriented, and type-safe programminglanguage derived from C and C ." That statement would apply equally well to Java. In fact, aftercomparing the two languages, it's obvious that prerelease descriptions of C# resemble Java more thanC . As Example 1 illustrates, the language features and syntax are similar. Example 1(a) is thecanonical "Hello World" program in Java, while Example 1(b) is the program in C#.(a)class HelloWorld {public static void main(String[] args) {System.out.println("Hello, World!");}}(b)class HelloWorld {public static void Main(string[] args) {System.Console.WriteLine("Hello, World!");}}Example 1: Hello World. (a) in Java; (b) in C#.But the resemblance goes beyond syntax, keywords, and delimiters. It also includes features that Javaand C# hold in common, such as:lllllllAutomatic garbage collection.Reflection for type information discovery.Source code is compiled to an intermediate bytecode.Just-in-Time (JIT) compilation compiles bytecode into native code.Everything must be in a class — no global functions or data.No multiple inheritance, although you can implement multiple interfaces.All classes derive from Object.

Dr Dobbs Journal: C# Versus Java (Feb 2001)lllllllllSecurity for restricting access to resources.Exceptions for error handling.Packages/namespaces for preventing type collision.Code comments as documentation.Arrays are bounds checked.GUI, networking, and threading support.No uninitialized variables.No pointers.No header files.C#: The Evolution of Visual J Why does Microsoft think we need another language? When Microsoft introduced Visual J inOctober 1996, it threw lots of resources into the project. Their efforts produced the fastest JVM on themarket and the Windows Foundation Classes (WFC), a set of Java classes that wrapped the Win32 API.Not coincidentally, Anders Hejlsberg, the project leader for WFC (and most famous as the author ofTurbo Pascal), is the chief architect for C#.Microsoft decided to make changes to Java to integrate it more closely with Windows. Some of thechanges — interfacing seamlessly with COM, refusing to support RMI and JNI, and adding delegates —caused it to break compliance with the Java Standard. Consequently, Sun Microsystems sued Microsoftin October 1997 for violating its Java license agreement. This doomed Microsoft's future developmentof Java and Visual J . However, Microsoft decided to take its advances in the Java language, Javacompiler, and JVM and morph them into an even more ambitious project — Microsoft .NET.Microsoft .NETThe term "Microsoft .NET" is similar to "Windows DNA" in that it refers to many things: a businessstrategy, development model, marketing pitch, development platform, and language run time. Butwhereas DNA is more of a "best practice" approach to development, at the heart of .NET is the CommonLanguage Runtime (CLR), a set of operating-system services and an execution engine that provides runtime support for .NET programs. You can think of the Common Language Runtime as fulfilling thesame role as the Java virtual machine.Programs written in C# are compiled into an intermediate language called "MSIL," the equivalent toJava bytecode or Visual Basic p-code. Any language that can be compiled to MSIL can take advantageof the CLR features such as garbage collection, reflection, metadata, versioning, events, and security, toname a few. In addition, a class written in one language can actually inherit from a class written inanother language and override its methods.Although this article is about C#, keep in mind that the class libraries and the CLR features are usableby any language that has an MSIL compiler. Initially, Microsoft will provide MSIL compilers for C#,Visual Basic, JScript, and Managed C . Third-party vendors have also developed .NET compilers for anumber of languages, including: Java (Rational), Eiffel (Interactive Software Engineering and MonashUniversity), Perl (ActiveState), Python (ActiveState), Scheme (Northwestern University), Smalltalk(Quasar Knowledge Systems), Cobol (Fujitsu), Component Pascal (Queensland University ofTechnology), APL (Dyalog), Standard ML (Microsoft Research-Cambridge), Mercury (University ofMelbourne), and Oberon (ETH Zentrum).It's interesting that Microsoft is pushing cross-language development while Sun/Java pushes cross-

Dr Dobbs Journal: C# Versus Java (Feb 2001)platform development.However, both approaches have their share of problems. Writing components in multiple languagesalways entails some interoperability problems. Moreover, there is always the problem of what to dowhen your Scheme programmer moves on to greener pastures. Cross-platform development has alsonever been flawless, as Java programmers well know, especially in the areas of GUIs and threading.C# Similarities to JavaIn addition to sharing a number of features, most of the keywords in Java have their C# counterpart.Some keywords are identical; for example, new, bool, this, break, static, class, throw, virtual, and null.This is expected since these keywords are derived from C . Interestingly, many keywords in Java thatdo not have direct C equivalents such as super, import, package, synchronized, and final, havedifferent names in C# (base, using, namespace, lock, and sealed, respectively). Table 1 summarizessome of the keywords and features that exist in both languages, but look slightly different in C#.Table 1: Cosmetic differences between Java and C#.

Dr Dobbs Journal: C# Versus Java (Feb 2001)The Object ClassAnother good example of cosmetic differences is the System.Object class in C#, which has the exactsame methods as the java.lang.Object class in Java except they are spelled differently. The clone methodin Java is called MemberwiseClone in C#, Java equals is Equals in C#, finalize is Finalize, getClass isgetType, hashCode is GetHashCode, and toString is ToString.Mere coincidence? Well, according to Anders Hejlsberg in a recent interview, "C# is not a Javaclone" ("Deep Inside C#: An Interview with Microsoft Chief Architect Anders Hejlsberg," by JohnOsborn, http://windows.oreilly.com/news/hejlsberg 0800.html). Right, it's a MemberwiseClone.Access ModifiersC# specifies access modifiers inline as part of the member definition just like Java does, instead of in ablock like C . The modifiers public and private have the exact same meanings in all three languages.However, "protected access" in Java is called "protected internal" in C#, and "package access" in Java iscalled "internal" in C#. C#'s protected modifier gives access to any subclass, even if it is not in the sameprogram. Another difference is that package access is the default for Java while private is the default forC#.ExceptionsSimilar to Java, try blocks in C# support the finally clause. There is no throws clause in C#, soeffectively, all exceptions are unchecked. You aren't forced to handle any exceptions. The opinion atMicrosoft, according to one employee, is that forcing developers to handle exceptions does more harmthan good. This leads to many catch(Exception e) exception handlers that don't do anything useful.This is an unfortunate decision because the throws clause makes it obvious which exceptions can bethrown by a method and are part of the method's contract. Otherwise, you are forced to read the calledmethod's source code to know which exceptions can be thrown.C# Improvements Over JavaSince C# and Java look and act alike in many ways, why bother using C# at all? As you might expectfrom a successor language, C# makes improvements over Java in some areas. In addition to addinginnovative features, C# has a simplified syntax for things such as iteration, events, and treating primitivetypes like objects, which reduces the amount of code you need to write.Reflection, Metadata, And Custom AttributesJava and C# compilers both emit metadata with the class bytecodes to support reflection. Reflectionprovides the ability to obtain type information dynamically and makes it possible for the run-timesystem to automatically provide implementations for run-time type identification, dynamic methodinvocation, serialization, marshaling, and scripting support.Microsoft has extended the notion of metadata with Custom Attributes, which let you markup a class,method, method parameter, and just about anything else, with extra information that can be accessed atrun time. When compiled, the attributes are combined with the EXE/DLL itself, so it is not possible forthem to be out of sync with the code. Attributes eliminate the need to maintain separate IDL files and

Dr Dobbs Journal: C# Versus Java (Feb 2001)type libraries. The C# compiler supports attributes for interoperating with legacy COM objects (Internettime indeed!) and the Win32 APIs, object serialization, conditional code execution, and deprecatingprogram entities.An example of where attributes are useful is specifying the XML schema to use when serializing a class(see Listing One). As you can see, the class is marked-up directly with bracketed attributes to indicatewhat XML node and attribute names to use when serializing or deserializing an Album object. ListingTwo is a program that creates an Album and serializes it. Listing Three is the resulting XML file. (Thecommand line for getting the XML serialization example to compile using the prerelease C# compiler iscsc.exe /r:System.Xml.dll /r:System.dll /r:System.Xml .Serialization.dll Albums.cs.)VersioningVersioning is a feature that is much needed in the Windows and Java development space. Windowsdevelopers are accustomed to "DLL Hell," where mismatched versions of DLLs can cause all kinds ofapplication problems. Java developers are also familiar with deprecated APIs and incompatible versionsof serialized objects.NET promises to fix these problems by letting you specify version dependencies between componentsand by supporting side-by-side execution of multiple versions of a component. This is similar to theversioning capabilities specified in the Java Product Versioning Specification, except that compile-time,installation time, and run-time enforcement is built-in.AssertionsAssertions are useful for sanity checking and enforcing the preconditions, postconditions, and invariantsof Design By Contract. They often catch bugs introduced by faulty design/logic, incorrect assumptions,integration, and code maintenance. Assertions are not supported in Java, although the Java CommunityProcess is working on it. Listing Four demonstrates assertions in C#, and Figure 1 shows the assertiondialog that appears. It lists the filename and line number where the assertion occurred, the general anddetailed error messages, and the stack trace.Figure 1: The assertion dialog.ref and out ParametersYou can pass parameters by reference or specify that they are output parameters by using the ref or outmodifiers. Since Java only allows pass-by-value, you have to perform silly tricks to get the same effect,such as using return values, passing in a one-element array, or putting objects inside wrapper classes. Anexample of pass-by-reference is: void swap(ref long n1, ref long n2);.

Dr Dobbs Journal: C# Versus Java (Feb 2001)Virtual MethodsBy default, all methods in Java are virtual and can be overridden by a derived class. In C#, as in C ,methods must be explicitly declared virtual. A common error in Java and C when overriding methodsis when someone inadvertently modifies the signature of the base class method. Because the signaturesdon't match, the derived class method hides instead of overriding the base class method. C# turns thisinto a compile-time error by requiring that the derived class use the override keyword to override avirtual method. In addition, a compile-time warning is given if a method in the derived class hides amethod in the base class. In this case, you can use the new keyword to remove the warning.enumsJava does not implement C/C -style enums because its designers claim that enums are not objectoriented. Face it, enums are a lot more typesafe than Java static final int constants. enums are not onlypresent in C#, they are typesafe, can have the , -, , and operators applied to them, and can beconverted to and from a string.decimal Data TypesC# decimal data types are 128 bits and have a greater precision and smaller range than floating-pointtypes. They are particularly useful for financial applications.switch StatementsBy default, case labels in a C# switch statement do not fall through to the next case label. In addition tobeing able to specify an integer in the switch and case statements, you can also specify a string.C# Syntactic SugarA method is just a function in which the first argument is a pointer to the object. Instead of calling foo(object,x,y), C /Java/C# allow you to write object.foo(x,y). This is an example of how syntactic sugarmakes object-oriented development easier. C# provides some sugar of its own to make componentoriented development easier.Delegates and EventsDelegates are a significant innovation for C#. They are object-oriented function pointers that canreference static or instance methods. They provide a type-safe mechanism for implementing callbackfunctions and events. C# supports single-cast, multicast, synchronous, and asynchronous delegates.Java provides for events by using the JavaBeans event model and adapter classes. Event handling in C#is simpler and only requires you to implement individual methods instead of entire interfaces. Delegateswere first introduced as a nonstandard feature of Visual J , much to the dismay of Sun Microsystems,which derided delegates as being "not object oriented." For Sun's delegates argument, ml, icles/delegates/truth.asp for Microsoft's rebuttal. (Someeven conjecture that the delegates issue was the turning point that lead to the Java lawsuit.)The event keyword introduces a delegate into your class that lets you fire events. Listing Five is a

Dr Dobbs Journal: C# Versus Java (Feb 2001)sample C# program that uses an event to notify a StockTracker when the price of a stock changes.Value TypesValue types in C# (long, int, char) can be treated just like reference types without requiring specialwrapper classes as in Java (java.lang.Long, for example). The compiler implicitly converts value typesinto objects (and vice versa) on demand through a process called "boxing and unboxing." However, thisincurs no overhead if the value type is never treated like an object. This allows C# developers to viewthe world as a unified type system in which all data types derive from object. Example 2 showsexamples of how each language lets you treat primitive types as objects.(a)int i 10;System.out.println((new Integer(i)).hashCode()); // Use wrapper class(b)int i 10;System.Console.WriteLine(i.GetHashCode()); // Conversion is implicitExample 2: Value types. (a) in Java; (b) in C#.PropertiesFor our purposes, properties and fields refer to two different concepts. A field is a class data member(long size, for example), whereas a property is a pair of getter and setter access methods that provideaccess to a field or calculate the needed values. Properties in C# are similar to JavaBeans properties inthat access to them is controlled through access methods. However, in C#, properties are directlysupported by the language instead of relying on reflection and naming conventions, as in JavaBeans.This leads to a clean and concise syntax that makes data hiding a breeze. Example 3 illustrates how theName property is implemented using the name field in both Java and C#.(a)String name;public String getName() { return name; }public void setName(String value) { name value; }Ex:obj.setName("Marc");if (obj.getName() ! "Marc")throw new Exception("That ain't me!");(b)string name;public string Name {get { return name; }set { name value; } // 'value' is the new value}Ex:obj.Name "Marc";if (obj.Name ! "Marc")throw new System.Exception("That ain't me!");Example 3: Implementing the Name property using the name field: (a) in Java; (b) in C#.

Dr Dobbs Journal: C# Versus Java (Feb 2001)The advantages of the C# property style is that the getter/setter methods are located in the same block ofcode and have a more intuitive syntax because properties are accessed exactly like normal fields.JavaBeans properties also look like normal fields when accessed from scripts or in a visual design tool,but not when accessing them from Java code.foreach-Style Iteration SyntaxThe foreach statement in C# (borrowed from Visual Basic) lets you easily enumerate over classes thatsupport the Enumerable interface, which includes arrays and collections. This eliminates the need towrite for(int i 0; i ary.length; i) and the getIterator/hasNext/next triad as you have to in Java andC . Listing Six demonstrates iteration in Java, while Listing Seven demonstrates foreach-styleiteration in C#.String FormattingA great example of C# syntactic sugar is string formatting. Java provides the MessageFormat class toallow printf-style formatting. The syntax in C# is much cleaner because you can pass a variable numberof parameters to the function. Example 4 shows off the string formatting features and variableparameters of C#. Both examples output Error: File not found. (Code 2).(a)// Create an object arrayObject args[] { "File not found.", new Integer(2) };// Format the format("Error: {0} (Code {1})",args));(b)System.Console.WriteLine("Error: {0} (Code {1})", "File not found.", 2);Example 4: String formatting. (a) in Java; (b) in C#.Operator Overloading and Cast OperatorsOperator overloading allows you to redefine the semantics of operators ( , -, , , and so on) for agiven type. When used properly, operator overloading can provide an intuitive syntax for treating userdefined types like primitive types. C# provides the operator keyword for this purpose.In addition to operator overloading, C# lets you define cast operators. For example, a class calledFraction can provide a cast operator that converts a Fraction into a double.C# Performance ImprovementsSeveral C# features result in performance improvements over Java. These include:llNever interpreted. The advent of Just-in-Time (JIT) compilers means that Java bytecodes areusually compiled directly into native code by the JVM instead of being interpreted. One differencewith the Common Language Runtime is that the bytecode is never interpreted, it is always JITed.Microsoft has a proven track record for writing the fastest JVM, so you can expect their MSILJITer to be fast.Native platform support for Win32 and COM is an improvement over the performance of J/Direct

Dr Dobbs Journal: C# Versus Java (Feb 2001)llland the Java Native Interface.The stackalloc operation is similar to new, except that it allocates memory for an array on thestack instead of the heap. Stack allocation is much faster than heap allocation and is not subject togarbage collection.A struct data type is exactly like an object, except that structs are value types instead of referencetypes and do not support inheritance. They can be allocated on the stack just like primitive typesand do not require the extra vtable overhead. Use structs to represent simple types, such as Point,Rect, Fraction, and so on. They lose their effectiveness when their size goes above 16 bytes.Code in C# can be marked unsafe to allow it to have direct memory access and prevent thegarbage collector from interfering.What's Not to Like?Neither Java nor C# support generic types (templates). However, a proposal has been submitted to theJava Community Process, and Microsoft Research at Cambridge is said to be developing a solutionfor .NET.Like J/Direct, the P/Invoke class library provides the ability for C# to talk to native Win32 APIs andDLLs. While this is a boon for interoperability, it requires writing C# function prototypes that have thesame signatures as the API functions. For example, handles (HWND, for example) are approximatedusing a C# int and pointers are approximated with ref parameters. This technique is prone to signaturemismatches that can cause unpredictable behavior and crashes.Similar to P/Invoke, COM Interop provides wrapper classes for allowing C# to use COM objects andvice versa. Unfortunately, certain types of COM interfaces are not 100-percent compatible withwrappers, which causes an impedance mismatch.ConclusionC# is Java with some nifty features, innovations, syntactic sugar, and performance enhancements thrownin. C#'s elegance, simplicity, and power promises to deliver Windows C developers from the pits ofboilerplate COM code and memory violations to the land of RAD. For Java programmers, C# picks upwhere Java leaves off by providing a high-performance, component-oriented language that integratestightly with Windows. Let's hope C# is as much fun as Java is to work with.DDJListing Oneusing System.NewXml;using System.Xml.Serialization;[XmlRoot("album", Namespace "music")]public class Album {[XmlElement("artist")]public string artist;[XmlElement("title")]public string title;[XmlArray("songs"), XmlArrayItem("song")]public string[] songs;}Back to Article

Dr Dobbs Journal: C# Versus Java (Feb 2001)Listing Twousing System.Xml.Serialization;using System.IO;class TestAlbum{public static void Main() {Album album new Album();album.artist "Sasha";album.title "Xpander";album.songs new string[5];album.songs[0] "Xpander Edit";album.songs[1] "Xpander";album.songs[2] "Belfunk";album.songs[3] "Rabbitweed";album.songs[4] "Baja";// Serialize the object to a fileFileStream fs new FileStream("Album.xml", FileMode.Create);XmlSerializer serializer new fs, album);}}Back to ArticleListing Three ?xml version "1.0"? album xmlns:xsi http://www.w3.org/1999/XMLSchema-instancexmlns "music" artist Sasha /artist title Xpander /title songs song Xpander Edit /song song Xpander /song song Belfunk /song song Rabbitweed /song song Baja /song /songs /album Back to ArticleListing Fourusing System.Diagnostics;class ConfigFile {bool isFileOpen;public void Open(string strFile) {// Pre-conditionsDebug.Assert(!isFileOpen, "Config file already open.","You can only call Open() once.");Debug.Assert(strFile.Length 0);isFileOpen true;// .}public static void Main() {

Dr Dobbs Journal: C# Versus Java (Feb 2001)ConfigFile file new ml"); // Causes an assertion!}}Back to ArticleListing Fiveusing System;delegate void PriceDecreasedDelegate(string name, long newPrice);// Called when the price dropsdelegate void PriceIncreasedDelegate(string name, long newPrice);// Called when the price increasesclass Stock {// Holds the price of a stockpublic Stock(string stockName, long startPrice) {name stockName;price startPrice;}public long Price {get { return price; }set {if (value price &&Fire OnPriceIncreased ! null) {Fire OnPriceIncreased(name, value); // Inform listeners} else if (value price &&Fire OnPriceDecreased ! null) {Fire OnPriceDecreased(name, value); // Inform listeners}price value; // Update the price}}// DATAstring name;long price;public event PriceDecreasedDelegate Fire OnPriceDecreased null;public event PriceIncreasedDelegate Fire OnPriceIncreased null;}class StockTracker {// Outputs a message when the stock price changespublic StockTracker(Stock stock) {// Connect the Stock events to our event handlersstock.Fire OnPriceDecreased new e OnPriceIncreased new PriceIncreasedDelegate(OnPriceIncreased);}// Signature of event handler must match the// PriceDecreasedDelegate delegate declarationprivate void OnPriceDecreased(string name, long val) {Console.WriteLine("Price of {0} dropped to {1}!", name, val);}private void OnPriceIncreased(string name, long val) {Console.WriteLine("Price of {0} rose to {1}!", name, val);}}

Dr Dobbs Journal: C# Versus Java (Feb 2001)class StockTester {// Test the eventspublic static void Main() {Stock ibm new Stock("IBM", 100);StockTracker tracker new StockTracker(ibm);// Update the stock priceibm.Price 125; // Outputs "Price of IBM rose to 125!"ibm.Price 90; // Outputs "Price of IBM dropped to 90!"}}Back to ArticleListing Siximport java.util.*;class Iterate {public static void main(String[] args) {// Enumerate command-line args arrayfor(int i 0; i args.length; i)System.out.println(args[i]);// Create a linked listLinkedList list new LinkedList();list.add("Cube Farm");list.add("Sasha & Digweed");// Enumerate the listListIterator it list.listIterator(0);while (it.hasNext())System.out.println(it.next());}}Back to ArticleListing Sevenusing System.Collections;class Iterate {public static void Main(string[] args) {// Enumerate command-line args arrayforeach (string arg in args)System.Console.WriteLine(arg);// Create a linked listObjectList list new ObjectList();list.Add("Cube Farm");list.Add("Sasha & Digweed");// Enumerate the listforeach (string str in list)System.Console.WriteLine(str);}}

Dr Dobbs Journal: C# Versus Java (Feb 2001)Back to ArticleCopyright 2004 CMP Media LLC, Dr. Dobb's Journal's Privacy Policy, Terms of Service,Comments: [email protected] Websites: BYTE.com, C/C Users Journal, Dr. Dobb's Journal, MSDN Magazine, SysAdmin, SD Expo, SD Magazine, Unixreview, Windows Developer Network, New Architect

The Object Class Another good example of cosmetic differences is the System.Object class in C#, which has the exact same methods as the java.lang.Object class in Java except they are spelled differently. The clone method in Java is called MemberwiseClone in C#, Java equals is Equals in C#, finalize is Finalize, getClass is getType, hashCode is GetHashCode, and toString is ToString.File Size: 572KB