Информация об изменениях

Сообщение Re: EnumerateFiles() от 08.07.2021 20:38

Изменено 08.07.2021 20:45 Qbit86

Re: EnumerateFiles()
Здравствуйте, Shmj, Вы писали:

S>Можно IEnumerable<T>, если этот список формируется динамически (yield return или прямая реализация шаблона).

S>К примеру, Directory.GetFiles() возвращает string[].

А Directory.EnumerateFiles() возвращает IEnumerable<string>.

S>...возвращает string[]. Насколько это правильно?


Это прибивает гвоздями решение аллоцировать массив менеджером памяти. Плохо для пользователей, которые пишут чувствительный к memory-трафику код.
В лучшем случае автор библиотеки это сделает через GC.AllocateUninitializedArray{T}(), но кто про него знает? (Не уверен, что его можно использовать с типом string.) А пользователь библиотеки может предоставить более эффективную для своего сценария стратегию получения массивов; скажем, через ArrayPool{T}.

S>Емнип, сами MS в своих Guidelines рекомендовали типа ReadOnlyCollection<T> в общих случаях.


Многие современные стандартные API и вовсе запрашивают выходной Span<string>. Правда, это требует API для предварительной оценки количества элементов, что вряд ли оправдано конкретно для списка файлов.

S>Кто серьезно относится к этому вопросу и что делаете?


Я сейрьёзно отношусь к этому вопросу, и вместо GetFiles() вероятнее всего сделал бы PopulateFiles(), передавая туда ICollection<string>, или лучше TCollection where TCollection : ICollection<string>, или вовсе конкретный класс коллекции, а может и Span<string>. Это не так декларативно, и сложнее в использовании, зато гибче. Если пользователю не нравится такой вызов и пофиг на производительность, он сможет и сам легко обернуть во что-нибудь, возвращающее массив.
Re: EnumerateFiles()
Здравствуйте, Shmj, Вы писали:

S>Можно IEnumerable<T>, если этот список формируется динамически (yield return или прямая реализация шаблона).

S>К примеру, Directory.GetFiles() возвращает string[].

А Directory.EnumerateFiles() возвращает IEnumerable<string>.

S>...возвращает string[]. Насколько это правильно?


Это прибивает гвоздями решение аллоцировать массив менеджером памяти. Плохо для пользователей, которые пишут чувствительный к memory-трафику код.
В лучшем случае автор библиотеки это сделает через GC.AllocateUninitializedArray{T}(), но кто про него знает? А пользователь библиотеки может предоставить более эффективную для своего сценария стратегию получения массивов; скажем, через ArrayPool{T}.

S>Емнип, сами MS в своих Guidelines рекомендовали типа ReadOnlyCollection<T> в общих случаях.


Многие современные стандартные API и вовсе запрашивают выходной Span<string>. Правда, это требует API для предварительной оценки количества элементов, что вряд ли оправдано конкретно для списка файлов.

S>Кто серьезно относится к этому вопросу и что делаете?


Я сейрьёзно отношусь к этому вопросу, и вместо GetFiles() вероятнее всего сделал бы PopulateFiles(), передавая туда ICollection<string>, или лучше TCollection where TCollection : ICollection<string>, или вовсе конкретный класс коллекции, а может и Span<string>. Это не так декларативно, и сложнее в использовании, зато гибче. Если пользователю не нравится такой вызов и пофиг на производительность, он сможет и сам легко обернуть во что-нибудь, возвращающее массив.