First off, your idea of what is an OOP "fundamental" is not a fundamental. The inventor of the term "object oriented", Alan Kay, famously said:
I made up the term 'object-oriented', and I can tell you I didn't have C++ in mind.
Certainly the idea that lexically "everything goes inside a class" is not a fundamental principle of OOP. It's not even clear to me that the idea of a "class" is fundamental to object-oriented programming; the "class-based inheritance" pattern is just one way of embedding into a language support for concepts such as message passing, data abstraction and implementation sharing.
Second, your implication that C# the language designers are trying to make a language that conforms to "fundamentals" of OOP is putting the cart before the horse. Rather, we want to make a language that supports large, diverse teams working together on versionable, independent, interacting software components on our platforms. OOP just happens to be a great way to do that, so that's what we're doing.
We are certainly not trying to make a "pure" OOP language by any means. We'll take ideas from any paradigm if they support real-world customer-benefitting scenarios. There are ideas in C# taken from OOP, from procedural programming, from functional programming, from dynamic languages, and so on.
Third, your question is logically inconsistent. You ask why you can define a delegate outside a class. But a delegate is a class. A delegate is a very special class; it is always sealed, it always inherits from System.MulticastDelegate, and it always has the same members. But it is a class. We give it special syntax to call out that it is a very special kind of class. It makes sense to be able to define a delegate class outside of a class.
Fourth, the ultimate reason why it is legal to put a delegate outside a class is because it is highly convenient to do so. What is the class that you think Func<T>
or EventHandler
should go inside? Would that class be "OOP"? According to conventional "OOP" wisdom, a class should represent a concept by associating operations with data; what conceptual class of things does your proposed parent class of Func<T>
represent, and what are the operations and data on it?
There is no such sensible outer class, and there are no operations or data associated with the "outer class" of Func<T>
. So why force the user to define a useless outer class, just to be conformant with someone's mistaken idea of what "OOP" means?