C# Strikes a Chord
Notable Differences
As previously stated, both C# and Java use single inheritance, but both allow
deriving additional method functionality from a commonly derived interface (see
Example 2 and Figure 1 below for more details). C# and Java stick
together as well on use of Unicode and precisely defining the bit-size of all
primitive types like char, short, int, float, double and others (C++
allows them to be implementation dependent). But C# then swings toward C++ and
uses struct and enum (but not union) in a departure
from Java. In C#, struct is the same as class, except they cannot
be derived and they are passed by value instead of by reference. The result
is some performance tuning options for programmers struct provides
a memory savings, but at the cost of the possible overhead of call by value,
whereas the opposite is true for class.
Example 2: Interface and unsafe code
// Demo C# program to illustrate interface and unsafe code using System; using System.Collections; // An interface defines one or more abstract methods interface Header{ void saythis(String s); } // Next, Demo derives Header class Demo : Header{ // so Demo must supply definitions of all Header's methods public void saythis(String s){ Console.WriteLine(" Header says {0}", s); } public static void Main(){ // Our "main" routine int ii = 0; //define this in Garbage Collection space unsafe { //Test our interface first Demo DemoHeader = new Demo(); DemoHeader.saythis("'Nice to be among the Magnolias again' !"); // Now demo 'unsafe' coding practices IDictionary varEnviron = Environment.GetEnvironmentVariables(); Console.WriteLine("\n There are {0} Environment variables", varEnviron.Keys.Count); fixed(int* ip = &ii){ //so fix 'ii' to be Garbage Collection secure with this block foreach(String eString in varEnviron.Keys){ *ip += 1; Console.WriteLine(" {0} {1} = {2}", *ip, eString, varEnviron[eString].ToString()); } } // End of fixed block } // End of unsafe block } }Figure 1. Output from code in Example 2.
But the biggest change for C# is that it allows use of pointers. The code
has to be marked with an unsafe keyword as shown in Example 2. The mechanism is primarily to provide for interfaces to COM and Win32
APIs. With the need to declare variables as fixed - to be excluded from
garbage collection explicitly, even when the variable is declared within an
unsafe block - I expect unsafe coding will be kept down to a minimum.
Of more interest than the return of pointers will be the return of C++ operator
overloading and preprocessing statements.
The curious thing with operator overloading is that unlike in C++, the assignment
operator cannot be overloaded. When a binary operator is overloaded, the corresponding
assignment operator is also implicitly overloaded. For example, an overload
of operator * is also an overload of operator *=. So in C# code:
public Matrix operator *(Matrix a, Matrix b){ //Code for Matrix multiplication}<BR> Matrix A; Matrix B; <BR> .... //After initializing, do Matrix multiply<BR> A * B; // is really equivalent to A *= B
So all binary operator overload methods are destructive of their lefthand side
operands. Not quite what you expected; however restoration of pre-processor
statements like #define and #if are also unexpected but a bit
more of a pleasant surprise.
Also interesting are the parts of C++ syntax that were dropped by both C# and
Java. We have already mentioned multiple inheritance and should mention friend
functions. Also, a whole range of compiler hints like register, inline,
auto and others have not been adopted by either C# or Java. But the biggest
omission by far is all of the templates and generic programming constructs in
C++. There may be two reasons for this. First, the syntax is brutal, as the
following line of C++ testifies:
template<class Ch, class Tr, class A> basic_string<Ch, Tr, A> operator+(const basic_string<Ch, Tr, A>&, const basic_string<Ch, Tr, A>&);
Second, C# has unified primitive types under Object. So now using a mix of primitive and objects together, for example in container classes or GUI routines, is simplified enough to warrant omission of templates.
But just as interesting is what has been retained in all three languages. The basic primitive types are all there. C# adds sbyte, uint, ulong, ushort, plus decimal. The flow of control statements are nearly identical, with C# restoring the foreach and goto. Hurrah: I think the goto has been unfairly maligned. Which is conceptually simpler: Java's labeled break or a goto ? Meanwhile, the three languages have stuck pretty close together on what the operators should be and do. And as we noted at the outset, more than 75 percent of the keywords are either common or have synonymous meanings. This lowers the learning curve no small blessing these days.
Next: Microsoft's New Executable Environment