When planning out my programs, I often start with a chain of thought like so:
A football team is just a list of football players. Therefore, I should
Classes should avoid deriving from classes and instead implement the minimal interfaces necessary.
Deriving from classes breaks encapsulation:
Among other things this makes it harder to refactor your code.
Classes are an implementation detail that should be hidden from other parts of your code.
In short a System.List
is a specific implementation of an abstract data type, that may or may not be appropriate now and in the future.
Conceptually the fact that the System.List data type is called "list" is a bit of a red-herring. A System.List
is a mutable ordered collection that supports amortized O(1) operations for adding, inserting, and removing elements, and O(1) operations for retrieving the number of elements or getting and setting element by index.
When designing a data structure, the simpler the interface is, the more flexible the code is. Just look at how powerful LINQ is for a demonstration of this.
When you think "list" you should start by saying to yourself, "I need to represent a collection of baseball players". So let's say you decide to model this with a class. What you should do first is decide what the minimal amount of interfaces that this class will need to expose.
Some questions that can help guide this process:
This way you will not be coupling other parts of the code to implementation details of your baseball players collection and will be free to change how it is implemented as long as you respect the interface.
By taking this approach you will find that code becomes easier to read, refactor, and reuse.
Implementing interfaces in a modern IDE should be easy. Right click and choose "Implement Interface". Then forward all of the implementations to a member class if you need to.
That said, if you find you are writing lots of boilerplate, it is potentially because you are exposing more functions than you should be. It is the same reason you shouldn't inherit from a class.
You can also design smaller interfaces that make sense for your application, and maybe just a couple of helper extension functions to map those interfaces to any others that you need. This is the approach I took in my own IArray
interface for the LinqArray library.