Tuesday, April 05, 2005
Why is C# operator overloading restricted?
Occaisionally it makes sense to borrow a style from somehwere else. For example, I come from a C++ background and would be comfortable with this way of reading items from standard input:
CInStream cin = new CInStream(Console.In);
double x,y,z;
cin >> out x >> out y >> out z;
There must be an 'out', because C# requires references to be specially marked, but otherwise it looks rather like the iostreams C++ library.
Quite apart from whether you like this style, it's a non-starter. First, the second argument of operator>> must be an integer. Clearly the designers felt that right-shift operators should not be arbitrarily redefined. Second, C# will not allow any old expression as a statement; to quote the ultimate authority (CSC) "error CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement". As the SDK comments, "The compiler generates an error when it encounters a meaningless statement". Third, the compiler gets very confused if you use 'out' in this context; it may only appear in function call lists and declarations.
Apart from the third problem (which comes from an insufficiently general grammar) these are deliberate restrictions. It would probably be rather easy to relax them. One can't second-guess an arbitrary expression in the presence of operator overloading, since such overloads may have side-effects. My question is, if one is going to have operator overloading, why not make it a first-class property of the language and allow it to be used without restrictions?
Operator overloading seems to have a bad press. Java is famous for not allowing it, and is generally against 'syntactical sugar' (except for '+' meaning string concatenation, of course). In a sample set of Java interview questions we get the received opinion: "Because C++ has proven by example that operator overloading makes code almost impossible to maintain."
My feeling is that imposing rules is not the job of the language. If you are the responsible adult in a programming project, it is appropriate for you to enforce rules, and one of those rules may be 'no operator overloading unless you can really convince me otherwise'. (I'm sure a sufficiently sophisticated version control system could enforce such code restrictions)
Part of the problem is that the naming problem is particularly intense with operators. The existing C-style operators all have very specific meanings, and moving far from these is going to confuse people. Operator abuse is often just a case of badly-named methods.
My guess is that the designers of C# wanted to restrict operator overloading so that it would be used for its most natural use, which is expressing arithmetric operations and comparisons for value types. There is a lot to be said for this; matrices, vectors, complex numbers, etc all define multiplication and it is convenient to use standard mathematical notation. But extra freedom could be very useful - in moderation.
