List <> не имеет виртуальных или защищенных членов - такие классы почти никогда не должны иметь подклассы.Кроме того, хотя возможно, что вам нужна полная функциональность List<string>
, если вы это сделаете - есть ли смысл создавать такой подкласс?
У подклассов есть ряд недостатков.Если вы объявите свой локальный тип как FundIdList
, то вы не сможете назначить ему, например, используя linq и .ToList
, так как ваш тип более конкретен.Я видел, как люди решают, что им нужны дополнительные функции в таких списках, а затем добавляют их в класс подклассов.Это проблематично, потому что реализация List игнорирует такие дополнительные биты и может нарушать ваши ограничения - например, если вы требуете уникальности и объявляете новый метод Add, любой, кто просто (юридически) повышает значение до List<string>
, например, передавая список в качестве параметранабранный как таковой будет использовать список по умолчанию Добавить, а не ваш новый Добавить.Вы можете только добавить функциональность, но никогда не удалять ее - и нет никаких защищенных или виртуальных членов, которые требуют использования подклассов для использования.
Таким образом, вы не можете реально добавить какую-либо функциональность, которую вы не могли бы с помощью метода расширения, и ваштипы больше не являются полностью совместимыми, что ограничивает то, что вы можете делать со своим списком.
Я предпочитаю объявлять структуру FundId
, содержащую строку, и реализовывать любые гарантии относительно этой строки, которые вам там нужны, а затем работать сList<FundId>
вместо List<string>
.
Наконец, вы действительно имеете в виду List<>
? Я вижу, что многие люди используют List<>
для вещей, для которых IEnumerable<>
или простые массивыболее подходят.Экспонировать ваш внутренний List
в API-интерфейсе особенно сложно, поскольку это означает, что любой пользователь API может добавлять / удалять / изменять элементы.Даже если вы сначала скопируете свой список, такое возвращаемое значение по-прежнему вводит в заблуждение, поскольку люди могут ожидать, что сможет добавлять / удалять / изменять элементы.И если вы не выставляете List
в API, а просто используете его для внутренней бухгалтерии, тогда объявить и использовать тип, который не добавляет никакой функциональности, а только документацию, не так интересно.
Заключение
Используйте только List<>
для внутренних устройств, и не делайте его подклассами, если вы это делаете.Если вам нужна какая-то явная безопасность типов, оберните string
в структуру (а не в класс, поскольку структура здесь более эффективна и имеет лучшую семантику: нет никакой путаницы между нулевой FundId
и пустой строкой и равенством объектови хэш-код работает, как и ожидалось, со структурами, но для классов необходимо указать вручную).Наконец, предоставьте IEnumerable<>
, если вам нужно поддерживать перечисление, или если вам также нужно индексирование, используйте простую оболочку ReadOnlyCollection<>
вокруг вашего списка, а не позволяйте клиенту API возиться с внутренними битами.Если вам действительно нужен API с изменяемым списком, ObservableCollection<>
как минимум позволяет вам реагировать на изменения, вносимые клиентом.