Grundsätzlich spricht nichts gegen Modularität, allerdings kann eine schlecht gewählte Schnittstelle einer optimalen Nutzung im Wege stehen. Bei einem Array ist es egal, ob man erst prüft, ob ein Element enthalten ist (Suche nach Index) und dann anhand des Index das Element abruft, bei einer verketteten Liste könnte das dazu führen, dass die Liste doppelt durchlaufen wird, wenn beim 2. Aufruf nur der Index übergeben wird, ohne dass das Listenelement zwischengespeichert wurde.
Sinnvoll wäre es, wenn entsprechende Implementierungen einen Iterator zur Verfügung stellen würden, anhand dessen alle Elemente der Liste abgelaufen werden könnten, da so geprüft werden kann, ob das Element enthalten ist, um es direkt verwenden zu können.
Das würde aber wieder den Vorteil sortierter Listen/Bäume/... zu Nichte machen, da in diesen schneller gesucht werden kann, wenn man davon ausgehen kann, dass alle Elemente immer sortiert sind, also wenn die Suche innerhalb der Liste durchgeführt wird.
Eine Lösung dafür wäre es, eine "TryGet"-Methode zu implementieren, deren Rückgabe aussagt, ob ein entsprechendes Element enthalten ist, damit über eine(n) übergebene(n) Referenz/Pointer das Element selbst zurückgegeben werden kann. Letzteres wird nicht in allen Sprachen direkt unterstützt, ließe sich aber über einen kleineren Umweg (Rückgabe beider Informationen in einem einzigen Objekt) erreichen.
Wenn man Performnce-kritischen Code schreibt, ist es offensichtlich, dass man sich möglichst frühzeitig auch ansehen sollte, an welchen Stellen wie viel Zeit verbraucht wird. Wenn man sich den Profiler aber auch schon "vorher" ansieht, wird man tendenziell auch davon abgehalten, (aus Performancesicht) schlechten Code zu schreiben. Sinn macht es also.