Это зависит.
Я видел, как этот вопрос задавался пару раз, и вот хороший пример, иллюстрирующий ответ "все зависит".
Рассмотрим следующий класс:
public class MyClass
{
public static IEnumerable<int> Test()
{
return new List<int> { 2, 3, 4 };
}
public static List<int> Test2()
{
return new List<int> { 2, 3, 4 };
}
}
Test
возвращает IEnumerable
, а Test2
возвращает конкретную реализацию интерфейса IEnumerable
(List
в этом случае). Какой метод самый лучший? Test
или Test2
?
На самом деле, оба семантически различны:
- Поскольку
Test
возвращает только IEnumerable
, подразумевает , что это часть контракта метода , что разработчик использует возвращенный объект в перечислении (foreach
).
- Поскольку
Test2
возвращает экземпляр List
, он позволяет пользователю получить доступ к объектам List
по индексу. Это совершенно другое использование возвращаемого объекта.
private static void Main(string[] args)
{
foreach (var z in MyClass.Test())
{
Console.WriteLine(z);
}
var f = MyClass.Test2()[0];
Console.ReadKey();
}
Если вы ожидаете, что разработчик будет использовать возвращенный объект только в перечислении, то вы можете использовать интерфейс в качестве возвращаемого типа. Если вы ожидаете, что разработчик будет использовать методы / свойства конкретной реализации интерфейса (в приведенном выше примере доступ к объекту по индексу), тогда вы можете вернуть конкретный тип.
Также помните, что иногда у вас нет выбора. Например, если вы хотите предоставить общедоступную коллекцию, которая должна использоваться для привязки Silverlight, вы должны вернуть ObservableCollection<T>
, а не IEnumerable<T>
, потому что системе привязок на самом деле требуется метод / свойства / поведение ObservableCollection
класс (IEnumerable
будет недостаточно для привязки к работе).
Чего следует избегать, так это метода, который возвращает IEnumerable<T>
и используется каждый раз с ToList()
.