C# (.NET) Design Flaws
- the
Reset()
method onIEnumerator<T>
was a mistake (for iterator blocks, the language spec even demands that this throws an exception) - the reflection methods that return arrays were, in Eric's view, a mistake
- array covariance was and remains an oddity
- Update: C# 4.0 with .NET 4.0 added covariant/contravariance support to generic interfaces (like
IEnumerable<out T>
andFunc<in T, out TResult>
, but not concrete types (likeList<T>
).
- Update: C# 4.0 with .NET 4.0 added covariant/contravariance support to generic interfaces (like
ApplicationException
rather fell out of favor - was that a mistake?- synchronized collections - a nice idea, but not necessarily useful in reality: you usually need to synchronize multiple operations (
Contains
, thenAdd
), so a collection that synchronizes distinct operations isn't all that useful- Update: The
System.Collections.Concurrent
types, withTryAdd
,GetOrAdd
,TryRemove
, etc were added in .NET Framework 4.0 - though methods that accept a factory delegate do not guarantee the factory will only be invoked once per key.
- Update: The
- more use could have been made of the
using
/lock
pattern - perhaps allowing them to share a re-usable (extensible?) syntax; you can simulate this by returningIDisposable
and usingusing
, but it could have been clearer - iterator blocks : no simple way of checking arguments ahead-of-time (rather than lazily). Sure, you can write two chained methods, but that is ugly
- simpler immutability would be nice; C# 4.0 helps a bit, but not quite enough
- no "this ref-type parameter cannot be null" support - although contracts (in 4.0) help with this somewhat. But syntax like
Foo(SqlConnection! connection)
(that injects a null-check /throw
) would be nice (contrast toint?
etc)- Update: This is fixed in C# 8.0.
- lack of support of operators and non-default constructors with generics; C# 4.0 solves this a bit with
dynamic
, or you can enable it like this - the iterator variable being declared outside the while in the
foreach
expansion, meaning that anon-methods/lambdas capture the single variable, rather than one per iteration (painful with threading/async/etc)- Update: This was fixed in C# 5.0.
TextWriter is a base class of StreamWriter. wtf?
That always confuses me to the extreme.
A small C# pet peev - constructors use the C++/Java syntax of having the constructor be the same name as the class.
New()
or ctor()
would have been much nicer.
And sure, tools such as coderush make this less of an issue for renaming classes, but from a readability POV, New() provides great clarity.