I agree emphatically with this post (for those poo-pooing the lack of ToString, there is a debugger attribute to provide a custom format for your class).
On top of the above list, I would also add the following reasonable requests:
- non-nullable reference types as a complement to nullable value types,
- allow overriding a struct's empty constructor,
- allow generic type constraints to specify sealed classes,
- I agree with another poster here that requested arbitrary constructor signatures when used as constraints, ie. where
T : new(string), or where T : new(string, int)
- I also agree with another poster here about fixing events, both for empty event lists and in the concurrent setting (though the latter is tricky),
- operators should be defined as extension methods, and not as static methods of the class (or not just as static methods at least),
- allow static properties and methods for interfaces (Java has this, but C# does not),
- allow event initialization in object initializers (only fields and properties are currently allowed),
- why is the "object initializer" syntax only usable when creating an object? Why not make it available at any time, ie.
var e = new Foo(); e { Bar = baz };
- fix quadratic enumerable behaviour,
- all collections should have immutable snapshots for iteration (ie. mutating the collection should not invalidate the iterator),
- tuples are easy to add, but an efficient closed algebraic type like "
Either" is not, so I'd love some way to declare a closed algebraic type and enforce exhaustive pattern matching on it (basically first-class support for the visitor pattern, but far more efficient); so just take enums, extend them with exhaustive pattern matching support, and don't allow invalid cases,
- I'd love support for pattern matching in general, but at the very least for object type testing; I also kinda like the switch syntax proposed in another post here,
- I agree with another post that the
System.IO classes, like Stream, are somewhat poorly designed; any interface that requires some implementations to throw NotSupportedException is a bad design,
IList should be much simpler than it is; in fact, this may be true for many of the concrete collection interfaces, like ICollection,
- too many methods throw exceptions, like IDictionary for instance,
- I would prefer a form of checked exceptions better than that available in Java (see the research on type and effect systems for how this can be done),
- fix various annoying corner cases in generic method overload resolution; for instance, try providing two overloaded extension methods, one that operates on reference types, and the other on nullable struct types, and see how your type inference likes that,
- provide a way to safely reflect on field and member names for interfaces like
INotifyPropertyChanged, that take the field name as a string; you can do this by using an extension method that takes a lambda with a MemberExpression, ie. () => Foo, but that's not very efficient,
- Update: C# 6.0 added the
nameof() operator for single member names, but it doesn't work in generics (nameof(T) == "T" instead of the actual type-argument's name: you still need to do typeof(T).Name)) - nor does it allow you to get a "path" string, e.g. nameof(this.ComplexProperty.Value) == "Value" limiting its possible applications.
- allow operators in interfaces, and make all core number types implement
IArithmetic; other useful shared operator interfaces are possible as well,
- make it harder to mutate object fields/properties, or at the very least, allow annotating immutable fields and make the type checker enforce it (just treat it as getter-only property fer chrissakes, it's not hard!); in fact, unify fields and properties in a more sensible way since there's no point in having both; C# 3.0's automatic properties are a first step in this direction, but they don't go far enough,
- Update: While C# had the
readonly keyword, and C# 6.0 added read-only auto-properties, though it isn't as stringent as true language support for immutable types and values.
- simplify declaring constructors; I like F#'s approach, but the other post here that requires simply "new" instead of the class name is better at least,
That's enough for now I suppose. These are all irritations I've run into in the past week. I could probably go on for hours if I really put my mind to it. C# 4.0 is already adding named, optional and default arguments, which I emphatically approve of.
Now for one unreasonable request:
- it'd be really, really nice if C#/CLR could support type constructor polymorphism, ie. generics over generics,
Pretty please? :-)