Andre's Blog
Perfection is when there is nothing left to take away
C# - the new abomination

I finally took a closer look at C#, which is another Microsoft's attempt at designing a programming language. Apparently, the previous one, Visual Basic, didn't quite work out, seeing how Microsoft decided to drop it in favor of the new, supposedly sharper, language.

The first impression was fairly promising - it's a C++/Java-like language with similar language constructs and data types, which is supposed to be simple to learn, yet powerful to deliver everything any other language has to offer. For those who likes juggling bytes on their own, it even allows so-called unsafe operations with actual pointers for those who need to bypass the safety net.

Well, the first impression evaporated fairly quickly once I started to dive into the details of language implementation. C# appeared to be designed by a group of marketing guys whose only goal was to cram as many bits and pieces into the language as possible, copying features from other languages, regardless whether it was consistent or not.

Parameter References

Just like Java, C# does some trickery when it comes to passing built-in types into methods. For example, instances of such types as String or Integer in Java are immutable, so the effect of passing them to methods is the same is if they were passed by value or as const references in C++. This allows Java to treat literal strings as if they were primitive types.

C# also defines string literals as objects, but does not make them immutable, so one would need a way to tell when method arguments can be modified inside a method and when changes made in a method should be discarded. In order to do this, C# defines value types and reference types, as well as keywords (ref and out) that allow passing value-type parameters by reference. If this is not convoluted enough, C# also defines that objects declared with the keyword struct are passed into methods by value and those declared with class are passed by reference. Imagine looking at a good old printout like this:

void method(A& a);       // C++ (by reference)
void method(A a);        // C++ (by value)
void method(A a) {...}   // C# (either, depending on what A is)

C++ method signature is clear and self-descriptive, while C# signature requires the developer to find where A is defined and only then see whether a value or a reference will be used. Interestingly enough, a Java developer would immediately say in this case: "a is passed by reference", since A is not one of the well known types passed by value.

Yes, I realize that ref or out can be used to override the default behavior, but this is exactly what I call inconsistent design. It even seems that Microsoft realized this on their own, so C# requires the caller explicitly specify how the parameter is passed into a method:

void method(ref A a) {...}
A a = new A();
method(ref a);

The ref in the call on the last line is redundant, because it is not possible to call method without ref anyway, so the compiler actually tells you to put ref in.

Strings

Another interesting example is how characters in an array are converted a string. Consider following code:

char[] a = new char[10];
string s = new string(a);

Now, an interesting question is what would s.Length evaluate to once the string is created. Tempted to say zero? After all, the initializer was a zero-initialized array. Well, that would be wrong - the length of the string is actually 10 and the code that is using this string is expected to check if the pointer is not null, if the length is not zero and if the first character is not zero:

if(s != null && s.Length != 0 && s[0] != 0)
    some_method(s);

Just like Java, C# claims their string characters to be encoded in UTF-16, but fails handle surrogate pairs (four-byte UTF-16 characters). For example

byte[] ba = new byte[4] { 0xF0, 0x90, 0x8D, 0x8A }; // one UTF-8 character
string s = Encoding.UTF8.GetString(ba);

, this code produces a string that reports its length as two, not one, as it should be.

Converting byte arrays is one another area where C# shows some strange design approaches. For example, if you would like to convert an array of bytes in Java, you would just use an appropriate String constructor:

byte ba[] = {0x41, 0x42};
String s = new String(ba, "US-ASCII");

, which makes sense - a string is constructed from a sequence of bytes. In C#, however, it's the encoding that does the conversion

byte[] ba = {0x43, 0x44};
string s = Encoding.ASCII.GetString(ba);

, which is not quite what you would expect, as the encoding is merely a mapping between character codes used in the transformation, not the object that actually does the transformation. So, can string in C# convert bytes to a string? Actually, it can, but only in unsafe code:

string s;
sbyte[] sba = {0x41, 0x42};
unsafe
{
   fixed (sbyte* bp = sba)
   {
	s = new string(bp, 0, 2, Encoding.ASCII);
   }
}

Not for the faint of heart, is it? Makes you wonder how one would come up with the most complicated way to deal with a simple thing.

const Objects

One of the important features in C++ is the ability to declare objects and methods as constant using the const keyword. A constant object cannot be changed and a constant method may only be called for a constant object. Straightforward and very helpful, especially when building threaded applications.

Looking at C#, I found that it has not one, but two keywords in relation to read-only data - const and readonly. Well, two is better than one, right? Not quite. The first one just defines a constant that has to be initialized immediately at the point of the definition and the second one defines a variable that must be initialized in the constructor, so it cannot be ever changed.

What about read-only references passed into methods? It sure would make code faster - after all you just have to push 4/8 bytes onto the stack instead of making a copy of a variable. Tough luck - C# is based on the assumption that processing power available to your application exceeds your needs and you can simply pass objects that you don't want modified by value.

Inner Beauty

A well-designed programming language has its inner beauty. It doesn't matter whether the language is all-powerful, like C++, or optimized for quick development and processing, like JavaScript, in order to be a beautiful language. C# reminds me of the species in Halo, called The Flood, which kills everything in their way and uses other species' bodies to spread through the universe. There is no inner beauty there.

 


The Flood

Comments:
Posted Mon Apr 7 00:09:59 EDT 2008 by Thunder Hog

I remember C# had another nice feature that used to drive me crazy. The DateTime is a structure in C#, and structures couldn't be set to null. So if you have, let's say, a class "Person" you couldn't make a "DateOfDeath" field nullable for a live individual. What value are you supposed to use in such a case?.

At last in Visual Studio 2008 Microsoft fixed it by making structures nullable.

Posted Tue May 17 21:06:52 EDT 2011 by Dude

Negativity.... gets you far in this world. 

Name:

Comment: