First thought is a response to “Downside: It’s harder to see that list in the Editor.” This isn’t much of a downside. I’ve observed that students of Unity tend to think of C# as a subordinate script language, which is prompted by Unity’s presentation of C#, even to the point of thinking scripts are the central programming concept instead of classes. While I have my own viewpoint about C# itself, I see no reason to view development from a Unity “script” viewpoint, but as the development of a C# application using the Unity framework. The editor’s ability to “see” and “edit” values from an attached object “script” isn’t all that advantageous given the viewpoint of C# as more central than merely “scripting”.
A concrete example is the potential conflict between default values assigned in code vs. that set within the editor. Although I know the object instantiates with the values from code, the Unity framework serializes the values from the editor, so the values used at runtime are those from the editor. While that can be a convenience for adjusting and debugging, it means that if one develops reusable code there can be confusion as to what initializing values are at work. If I reuse a class which relied upon the settings from the editor, the new instantiation will rely, at first, on the values from code. Now I have two places to edit, and that can be as much a detriment as a convenience.
More generally, most editor configuration of the code (and only the code) creates a dependent relationship upon the editor. This comes up in synchronization, for example. If code is built which demonstrates an issue at initialization, and the editor is used to control the order of “Start” or “Awake” functions to solve that, then while the problem is “patched” to work, the original problem is still in the code. If, instead, the problem is solved in the code, there’s no need to use the editor to “patch” it to work. To me, this is a fundamental argument between the convenience of Unity editor’s inspector and the habits of professional programmers.
In my view that extends to your larger question, about C# objects that aren’t derived from MonoBehaviour. More generally, the beginner and intermediate level thought process should be on the notion of what class should perform what methods. If a method is really a MonoBehaviour concept, it should be performed in a MonoBehaviour derivative. If it isn’t strictly a MonoBehaviour concept, there’s no good reason to put the method in a MonoBehaviour derivative beyond mere convenience (or mediocrity).
Theres no reason, for example, not to use List<> generics for storage as members of MonoBehaviour objects, but List<> is part of C#, not Unity. It is a primary clue to the real answer to your question. Any design pattern can and should be implemented as independently from MonoBehaviour as the concept being implemented indicates. If there is already a MonoBehaviour object acting as a singleton, perhaps there’s a reason to base other singleton pattern work on that class.
Your observation that a lot of GameObject or MonoBehaviour classes comes with weight is exactly on point. Unless there’s a reason to inherit form MonoBehaviour, or otherwise become a component, classes independent of Unity will benefit from their independence. Vector3 itself is an example. It would likely operate outside of Unity to good effect.
Tasks, threads and other paradigms will do well on their own, but the typical caveats of synchronization may apply, but are worth it. Think of code in Unity less from the viewpoint of the Unity editor created scripts and more like a C# application that uses Unity as a framework. There’s nothing but upside in reality, if you view the minor issue of inspector visibility as a non-issue (because, it’s code in this viewpoint, not a Unity editor controlled development processes).