C#'s Greatest Mistakes by Jon Skeet
oredev.org
oredev.org
----------------------------------
wish: static interfaces for use in the context of generic type constraints
static interface ISummable<T>
{
T operator +(T arg1, T arg2);
}
which then lets you write
static T Sum<T>(IEnumerabel<T> source) where T : ISummable<T> { }
----------------------------------gripe: array covariance (which the designers copied from java even though people knew it was a mistake even when java had it):
//the following is still valid and will happily compile and run
string[] strings = new string[5];
object[] objects = strings;
objects[0] = new Exception();
----------------------------------wish: non-nullable references (ackowledges that it is a hard problem but "it would be nice to have")
----------------------------------
wish/gripe: c# enums are labels for numbers which let you write things like:
enum Color {red = 0, green = 1, blue =2}
Color c = (Color) 5;
Color c2 = 0.0;
he wants to see java-like enums which enforce the idea that you're dealing with a restricted set of values.----------------------------------
wish: Read-only keyword for auto-properties
.net 3 made it easy to tack mutable properties onto your class
string Name{get;set;}
Jon wants to see: string Name{ readonly get; }
which tells the world that not only is Name immutable externally to your class, but internally as well. string Name { get; private set; }
does not get you there, since the property is still fully mutable within your class.----------------------------------
wish: sealing/unsealing classes
this was his self-proclaimed controversial point
he either wants to see classes sealed by default and then unsealed with an explicit 'unsealed' keyword or he wants the default class template in Visual Studio to demand that the programmer pick one or the other
----------------------------------
gripe: object is bloated, cut Equals() and HashCode()
writing equals in a type hierarchy is a pain and gets messy when you drill down into the derived types
let authors "opt in" to equality
want a map of <T>? or a dictionary of <T>? you have to provide an equality comparer
"there doesn't have to be one canonical idea of equality for a type so why is it in object"?
This is good thread also
http://social.msdn.microsoft.com/Forums/en/csharplanguage/th...
I disagree on getting rid of Equals if for no other reason it's implicitly used often (like in collections). And if there is no canonical idea of equality, that's what overriding Equals is for, and what Object.ReferenceEquals is for (return yourself to the base notion of equality when you need it).
The Comparable interface shows how it should be done.
(But on the other hand, if you were starting over it would be better to learn from Go's interfaces.)
This of course, only makes sense in the post-generic world of .net +2.0 so he does excuse their presence as a vestige of 1.1.
I dunno, I haven't actually watched this presentation so maybe I just need more context. But I've been programming in C# since it came out and not once have I ever had any real issues with Equals and all of its related methods.
As with the case of explicitly sealed/unsealed classes, it seems like Jon's MO is to make programmers think about some of these things more carefully rather than have a "correct 90% of the time" default; a sentiment which I can definitely appreciate. :)
Anyway, he discusses it at approximately the 36 minute mark. Well worth a look.
What are you saying - that if it was copied from Java, it must be OK? It is not impossible that object is both copied from Java and bloated.
I disagree on getting rid of Equals if for no other reason it's implicitly used often
But it isn't used often. Take an application of yours. What percentage of the types that you have defined in it need to worry about equality over and above ReferenceEquals? You may have collections of customer, but never collections of CustomerFactory, CustomerRepository, CustomerController, CustomerEditForm, etc...
And if there is no canonical idea of equality, that's what overriding Equals is for
If you override equals, you can only have one kind of non-reference equality per type, which is what Jon Skeet says is not always the right thing.
public string MyString{set;get;}
In order to do the same with an immutable property requires a fair bit more code. private readonly string myString;
public string MyString
{
get
{
return myString;
}
}
Replacing all of that with public readonly string MyString{get;set;}
would be handy, and work with the way the language currently does.Deleted comment
Heck, I'd love a way of saying "immutable class" in the same way you can with a "static class", just to ensure I haven't missed anything!
Creating an accurate transcript of a live event is time consuming, and "hard" (well, it's tedious, which most people take to mean hard) to do right. Even if you don't any qualms crowd sourcing for something like this, you still need to manage the crowd sourcing, and get an edit cycle in there.
TL;DR; Free things are free for a reason.
Nice. I wonder what he thinks of stab:
http://code.google.com/p/stab-language/
So far, stab is a 1-man hobby project, but the guy seems incredibly prolific. Besides the compiler, he recently started work on an Eclipse plugin as well.
One interesting take-away was "languages should support good habits and make anti-patterns harder" (paraphrased roughly, of course). So it comes down to what one thinks good or bad habits are.
The video further reminded me of C#/.net's ginormous number of classes, interfaces and intermediate classes - it is standard procedure to use three different class-types to get a row of data from a database query. Thus my view would be that c#'s many clever looping and generics patterns actually are enabling tools the anti-pattern of too many classes/excessive indirection.
Thus it seems like Ruby's "Duck-typing", where you pass a single array around even when it's used slightly differently all around, is a general approach which allows you to escape this hell.