Agreed on #3, a lot of the BCL is just miserable in terms of design. There have been improvements lately but I'm still stuck using my own custom containers for various cases.
One good move the BCL and runtime teams have made over time is to just expose more unsafe primitives so you can easily build your own stuff - the Memory and Unsafe classes give you lots of useful tools, Span<T> and Memory<T> let you safely work with memory allocated in various ways, and various BCL stuff has been updated to accept Spans instead of requiring you to use managed arrays.