Search code examples
c#interfaceconcreteclass

Should the return type of a method declaration be interface or concrete class?


In general scenario, the interface or abstract class is often the appropriate decision, am I right?

But in some cases, it looks like the concrete class is better. For instance,

public string Replace(string old, string new)

The Replace method of String returns a concrete class. (It's just an example, although String doesn't implement any interfaces.)

My question is

  1. When should I return an interface, and when should I return a concrete class?

  2. Is it a part of program to an interface, not an implementation for returning an interface?


Solution

  • It depends.

    I've seen this question asked a couple of times, and here's a nice example to illustrate the "it depends" answer.

    Consider the following class:

    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 returns an IEnumerable and Test2 returns a concrete implementation of the IEnumerable interface (List in that case). What is the best method? Test or Test2?

    Actually, both are semantically different:

    • As Test only returns an IEnumerable, it implies that it's a part of the method contract that the developer uses the returned object in an enumeration (foreach).
    • As Test2 returns a List instance, it allows the user to access to the objects of the List by index. It's a totally different utilization of the returned object.

    private static void Main(string[] args)
    {
        foreach (var z in MyClass.Test())
        {
            Console.WriteLine(z);
        }
    
        var f = MyClass.Test2()[0];
    
        Console.ReadKey();
    }
    

    If you expect the developer to use the returned object in an enumeration only, then you could use the interface as return type. If you expect the developer to use methods/properties of the concrete implementation of the interface (in the above example, access to object by index), then you could return a concrete type.

    Also remember that sometimes you have no choice. For example, if you want to expose a public collection that should be used for a Silverlight binding, then you should return ObservableCollection<T>, not IEnumerable<T>, because the binding system actually needs the method/properties/behavior of the ObservableCollection class (IEnumerable would be not sufficient for the binding to work).

    What you should avoid is a method that returns IEnumerable<T> and that is used with ToList() every time.