In C# or Java you're never going to write double linked generic dynamic lists. You just won't.
Don't say that too fast.
I once ran into the problem that I had a few 100,000 short lists, with around 1,000,000 elements in them in total. More elements would be highly desirable. If you look at what Java lists do, you realize they add an object for each list (so 100,000 additional objects), and an object[1] for each element in a list (hello another 1,000,000 objects).
Normally not much of a problem, but my elements were really small, so the additional objects would have equal size or be even larger, doubling the memory requirements. Clearly an unacceptable solution (derived thanks to my understanding of Java list). Luckily I knew how to make a double linked list in C. That got rid of all the cruft, doubling the number of elements I could store before hitting the JVM memory ceiling.
While my example was perhaps a bit extreme, it generally is very useful to know and understand how the standard things like dictionary, set, list, etc work, and what happens with performance if you add a lot of data in them (the big-O complexity notation).
In addition, data structures and algorithms is a large collection of solidly engineered smart tricks. Studying them makes that you see and understand a lot of those tricks. That makes you a better programmer. when you run into a unknown problem, you may find it looks like an algorithm you saw before, you'll remember its trick, and perhaps that will work in your new problem too? That expands your bag of tricks significantly.
[1] I needed fast arbitrary removal, so ArrayList was not feasible.