One of the greatest lingering flaws in both C# and Java is the lack of metaclasses.
Because classes aren't real objects and therefore not necessarily also instances of other classes (their metaclasses) as they would be in Smalltalk, there is no class-side equivalent of "self/this," nor of "super." In effect, you cannot write static (class) methods that call other static methods without explicitly referencing the classes on which those other methods are defined, completely breaking class-side inheritance and rendering class behavior (and instance creation in particular) needlessly brittle.
I believe the explosion of factories, abstract factories, and just generally over-engineered object construction and initialization schemes in Java and C# would have been side-stepped if both languages had always had a proper metaclass hierarchy paralleling the regular class hierarchy, as well as some form of local type inference.
Because classes aren't real objects and therefore not necessarily also instances of other classes (their metaclasses) as they would be in Smalltalk, there is no class-side equivalent of "self/this," nor of "super." In effect, you cannot write static (class) methods that call other static methods without explicitly referencing the classes on which those other methods are defined, completely breaking class-side inheritance and rendering class behavior (and instance creation in particular) needlessly brittle.
I believe the explosion of factories, abstract factories, and just generally over-engineered object construction and initialization schemes in Java and C# would have been side-stepped if both languages had always had a proper metaclass hierarchy paralleling the regular class hierarchy, as well as some form of local type inference.