Повернення інтерфейсу або класу


9

Припустимо, у мене є метод

public List<User> GetBatchOfUsers(IEnumerable<int> userIDs)
{
    List<User> users = new List<User>();

    // some database stuff

    return users;
}

Я читав, що було б краще повернути інтерфейс (або IListабо IEnumerable) на відміну від повернення a List. Деякі аргументи, які я чув для цього, це те, що він приховує дані та надає розробнику API гнучкість зміни внутрішнього представлення даних на більш пізню дату.

Моє занепокоєння з приводу повернення даних IEnumerableполягає в тому, що ви втрачаєте функціональність, наприклад, випадковий доступ та Countвласність.

Я знаю, що приймати IEnumerableпараметр має сенс, оскільки він дає споживачеві найкращу гнучкість надсилати дані до мого методу, мінімалістичний набір вимог до методу для роботи.

Яка найкраща практика для типу повернення?


5
Набагато важливіше: прийняти інтерфейс як тип параметра.
Майкл Боргвардт

Відповіді:


10

Взагалі кажучи, ви можете почати з інтерфейсів і рухатися, щоб видати тип бетону як тип повернення, якщо виявите, що додаткові методи використовуєте частіше, ніж очікувалося.

Що ж, якщо ви повернете інтерфейс, ви збережете більшу гнучкість. Пізніше ви можете змінити реалізацію, щоб повернути інший тип бетону. З іншого боку, це, очевидно, дає абоненту менше інформації, тому вони, можливо, не зможуть виконати певні операції. (Наприклад: якщо ви повертаєтеся List<T>, абонент може використовувати ConvertAll і т. Д. ... чого вони не можуть, якщо ви лише оголосите, що повертаєтесь IList<T>.) У деяких ситуаціях варто вказати конкретний тип.

Щодо методу Count або Sort, для цього не існує стандартних інтерфейсів колекції. Однак ви можете написати метод розширення для сортування чи підрахунку будь-якого IList.


Я думаю, це насправді не важке правило?
Матвій

так, це дійсно залежить від використання.
Юсубов

1

Якщо вам потрібна ваша колекція, Countяку ви можете використовувати ICollection<T>, що є загальним.


-1. Графа вже обговорювали, і ця відповідь не додає нічого нового
superM

@Konrad Rudolph, це не відповідь, його коментар.
superM

@superM Я думаю, що це достатньо цінно, щоб заслужити власну відповідь, оскільки в ній чітко розглядаються причини OP для рішення проти інтерфейсів.
Конрад Рудольф

1

Ви повертаєте те, що є доцільним для методу, який ви визначаєте. Це те, що ви робите, повертаючи серію предметів (фокус робиться на предметах), чи повертаєте колекцію предметів (фокус робиться на колекції в цілому)? Чи варто допускати розбіжність у виконанні колекції? Якщо ніколи не буде сенсу використовувати генератор або HashSetпросто використовувати List.


1

Специфічний для прикладу метод: Ви маєте рацію, що повернення IEnmuerable<T>означатиме, що ви втратите функціональність Countта індексацію (хоча ви можете використовувати методи LINQ Count()і ElementAt()які ефективно реалізуються, якщо тип, який вони використовуються на фактичних реалізаціях IList<T>).

Якби ви повернулися IList<T>, ви втратили б певну функціональність, але, напевне, виграш варто.

Але ще краще буде щось середнє IEnumerable<T>і IList<T>, оскільки, швидше за все, споживачеві немає сенсу мутувати повернуту колекцію, але це має сенс використовувати Countабо індексувати.

У .Net 4.5, є такий інтерфейс: IReadOnlyList<T>.


IReadOnlyListдобре звучить, коли я можу отримати VS2013, дякую!
Метью
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.