Question

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?

Was it helpful?

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.

OTHER TIPS

In my opinion it depends, say if you have a method which is used in a tightly coupled fashion, i.e. Class 1 calls Method A on Class 2 and always wants a certain type and is the only time that method is called then you could argue there is no point. An example of this could be returning IEnumerable, where the method creates the collection as a list, then returns it as IEnumerable, Class 1 then consumes that as a list anyway so the return would need ToList() being called upon it anyway.

However when I'm writing a more decouple interface between classes such as a Data layer, I always prefer to return the lowest common denomnator (IEnumarable for example) and allow the consumer which I may have no knowledge of decide what to do with it.

You are getting the Program to an interface, not an implementation wrong I believe. What the GOF mean by program to an interface, is the interface of the type.

They define the interface of an object as all the methods that are visible from the exterior. So their definition of interface in this case is different from the one you have in C# for instance.

Concerning your question, I would believe that it is probably better to return the abstract class. Will it work if you return any object derived from that abstract class ? If yes, then return the abstract class. If not, go more specific, and return a derived type.

Depends on how much access you want to give to the user of your code!

I mean, returning List<AccountStatement> to a user will not make any sense. Because, you would not like the user of your code to ADD a new statement in this collection (A statement should get created on booking a particular transaction)

So, in this case you may just return IEnumerable<AccountStatement> - only read access.

In general, I do support the idea of returning Interfaces from methods for following reasons:

  • You get better control over access you give to your object to outside world.
  • You get to hide the implementation details (for that instance, even your class can remain internal to assembly)
  • It is in-line with Interface Segregation Principle (only expose the behavior you want by returning, and implementing, the right interface).

Btw, your example of returning "string" is not of much use. It is a primitive data type (I mean a native data type in mscorlib), and there is not much to hide/show in this object.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top