One of the C# oddities I noted in my recent article was that I find it odd that creating a numeric type with less-than, greater-than, and similar operators requires implementing a lot of redundant methods, methods whose values could be deduced by simply implementing a comparator. For an example of such, see my previous series of articles on implementing math from scratch.
A number of people commented that my scheme does not work in a world with nullable arithmetic (or, similarly, NaN semantics, which are similar enough that I’m not going to call out the subtle differences here.) That reminded me that I’d been intending for some time to point out that when it comes to comparison operators, nullable arithmetic is deeply weird. Check out this little program: Continue reading
Hey everyone, I am finally back from my many travels this summer and looking forward to doing some blogging this autumn. I’ll post some vacation photos when I have them sorted out. Until then, here’s an article that the nice people at InformIT asked me to write: what are my ten least favourite C# features?
I’m sure I missed some of your least favourites; I’d love to know what your pet peeves are in the comments here or on the article itself.
I briefly discussed copy-paste errors in code earlier; though this is a rich area of defects that I will probably at some point go into more detail on, that’s not for today.
Though this is a trivial little issue, I think it is worthwhile to illustrate how to think about these sorts of defects.
What is the defect?
Last week Jon Skeet “tweeted” humorously that in his work on the ECMA committee that is standardizing C#, they had found a mistake in the specification that was probably my fault; some commenters suggested that perhaps hell had also frozen over.
This is a sequel to my 2009 post about division of long integers.
I am occasionally asked why this code produces a bizarre error message:
Console.WriteLine(Math.Round(i / 6000000000, 5));
i is an integer.
The error is:
The call is ambiguous between the following methods:
'System.Math.Round(double, int)' and 'System.Math.Round(decimal, int)'
Um, what the heck? Continue reading
One of the nice things about a project as large as the Roslyn project is that you have an opportunity to really think hard about your past mistakes and hopefully fix them. When I was working on getting these error messages reported in Roslyn I realized that trying to match exactly the behavior of the original compiler would be actively making the world a worse place, so I took a big step back and started sending a lot of emails to Mads, Neal, Anthony and the rest of the Roslyn gang to try and get a better design worked out. All the godawful nonsense I told you about in the previous two episodes will be fixed in Roslyn.
Last time I gave you the challenge to find a case where the same simple name means two different things, without introducing a new local/parameter/range variable into scope, that produces an error. It seems like it ought to be impossible; if nothing new has been introduced to a local scope then how can name resolution choose two different things? The relevant section of the C# specification (188.8.131.52 Invariant meaning in blocks) only gives the example I gave last time, of a local having the same name as a field.
The key to solving the riddle is a little-known rule about resolving a name from a set of possible class members: Continue reading
There’s a saying amongst programming language designers that every language is a response to previous languages; the designers of C# were, and still are, very deliberate about learning from the mistakes and successes of similar languages such as C, C++, Java, Scala and so on. One feature of C# that I have a love-hate relationship with is a direct response to a dangerous feature of C++, whereby the same name can be used to mean two different things throughout a block. I’ve already discussed the relevant rules of C# at length, so review my earlier posting before you read on.
OK, welcome back. Summing up:
- C++ allows one name to mean two things when one local variable shadows another.
- C++ allows one name to mean two things when one usage of a name refers to a member and a local variable of the same name is declared later.
- Both of these features make it harder to understand, debug and maintain programs.
- C# makes all that illegal; every simple name must have a unique meaning throughout its containing block, which implies that the name of a local variable may not shadow any other local or be used to refer to any member.
I have a love-hate relationship with this “unique meaning” feature, which we are going to look at in absurd depth in this series.