3 ms·
This is neat, but also super confusing. Is the ability to build class hierarchies not the ultimate reason to use C#, an Object-Oriented language? Which one of
by martijn_himself 7y ago
This is neat, but also super confusing.
Is the ability to build class hierarchies not the ultimate reason to use C#, an Object-Oriented language? Which one of the two is idiomatic?
Great, now we have code littered with methods that take objects as parameters, so we have no clue what to actually pass to the method?
C# is a fantastic language but I feel increasingly lost with the barrage of new features added to it.
- 1propionyl 7y agoClass hierarchies are not a desirable feature of object-oriented languages, they're an unfortunate side effect of their historical development. (For example, early versions of Java did not actually have the interface keyword at all.) There are several very good reasons that the inherited wisdom about OOP includes such phrases as "prefer composition and delegation over inheritance". There are some cases where class hierarchies are actually good, but they're far rarer than most would suspect. The Liskov Substitution Principle is less of a guide as to how to use inheritance as much as it is a guide as to when you should not be using inheritance at all. And to address your point: the only time objects with class hierarchy and subclases should be accepted as arguments to methods is precisely when the LSP holds. Otherwise, you're gonna have a bad time.
- martijn_himself 7y agoThese are all valid points and it shows my lack of understanding (same with the other comments), even though I use C# on a semi-regular basis I have a lot to learn! I don't envy any newcomers to the language though, there is so much to take in.
- 1propionyl 7y agoMy general advice to anyone working with C# is the same advice given by the authors of Smalltalk to developers. 1) Always prefer composition and delegation to inheritance. 2) Always prefer interface inheritance to implementation inheritance even if in the short term it results in code clones. 3) If you intend to have multiple subclasses that adhere to the Liskov Substitution Principle, it is always better to have IFoo and X implements IFoo, Y implements IFoo... than it is to have abstract class Foo where X, Y extend Foo. You can still do that, behind the scenes, but your public interface should whenever possible be nearly entirely interfaces and concrete classes. 4) Inheriting the body/behavior of methods is seductive but ultimately only a poor excuse for not delegating that will create maintenance headaches down the line.
- goto11 7y agoNo, the ultimate reason to use C# is to solve problems and build useful applications! But you are correct that method overriding and pattern matching partially solve the same problem in different ways. C# is not really a pure OO "one way to do it" language anymore, it is a multi-paradigm language, for better or worse. Arguably it have been since anonymous function was added.
- 1propionyl 7y agoMethod overriding and pattern matching actually solve the same problem in precisely opposite ways. In the functional programming community, this is referred to as "the expression problem". To understand this problem properly you must first accept the idea that every object (or class of objects) in an OO context is essentially an interpreter defined by how it responds to sequential messages (methods). The crux of the expression problem is the tension between adding new operations over a type (i.e. new methods on the base class of a hierarchy) which requires implanting that method for every existing subclass... and adding new types (new subclases) over which an existing operation (method from the parent class) applies, which requires implementing every existing for the new type (subclass). There are some "clever" approaches to "solving" this problem, but they only really make sense for types that look and act like ASTs. Despite many complex programs essentially being interpreters for some internal "language", this isn't as useful as one might hope, and the machinery necessary to "solve" the problem relies on a lot of compiler and language extensions. If you want an example of (uh) "solving" the expression problem, the canonical starting point is Wouter Swierstra's "Data Types a la Carte" paper.
- fsloth 7y ago"Is the ability to build class hierarchies not the ultimate reason to use C#, an Object-Oriented language?" The ultimate reason to use C# is because it's a modern managed language with an excellent base library, excellent tooling and excellent debugging experience. Object oriented hierarchy is not a value in itself. Often it's an antipattern. I'd day 80% of time you are off much better by cleanly separating your program to "data" and "algorithms", and manipulating data as far as possible in immutable fashion. I.e. when mutating an array, don't overwrite elements, rather copy the values to new array. This will be easier to understand, and likely faster due to how memory and caches work on modern platforms. Etc. "Which one of the two is idiomatic?" Idiomatic is a weak argument when talking about programming. Either the problem is trivial, hence all you have left are to discuss trivialities, or you don't understand the problem and are therefore discussing things of very little consequence. Writing maintainable, understandable code is important. But "idiomatic" gives the idea that there is some higher level ultimate truth on what is always the best formulation for each and every problem. If you are writing boiler-plate code, then yes, best pattern will emerge eventually. But then it should be self evident which is best way to move forward. Hence, 'idiomatic' once again loses it's value.
- louthy 7y agoAgree with everything here > Writing maintainable, understandable code is important. But "idiomatic" gives the idea that there is some higher level ultimate truth on what is always the best formulation for each and every problem. This is the sentence that really rings true. Idiomatic is often dogmatic, especially in the OO language world. As far as I am aware, there's very little research backing up the GoF doctrine but it's often rattled off as "what you should be doing" and idiomatic. As someone who 'saw the light' on this later in my career I have since moved to using functional programming (in C#, because the project I work on started life as OO and is a never ending huge web-app); Mathematics has a lot more to say about correctness than the imperative/OOP world of idioms, and I find I can trust my code much more than in the past. I needed to create my own Base Class Library to make it happen [1], which has been a labour of love, but has fundamentally changed our multi-million line code-base for the better. But, obviously it has to fight against the baked-in mentality of devs in the OO/C# space by providing a non-idiomatic solution. The next step on the evolution will be category theoretic approaches (I believe), languages like Statebox are already starting down this path. How languages like C#, that still have the legacy of the OO world baked into its framework and grammar, will cope with this evolution long-term remains to be seen. However, right now I think they're just about getting it right. And C# especially is still one of the easiest languages to be productive in, with a world class tool chain. [1] https://github.com/louthy/language-ext https://github.com/louthy/language-ext