A scenario often arises when attempting to make some existing code reusable. I introduce an interface to represent the commonality between some new feature I’m implementing and some existing functionality, but I become stuck when trying to access the existing concrete object.

Hopefully the following C# example can explain my problem.

Let’s say I have the following existing code:

public class Program
{
    public static void Main()
    {
        var books = new[]
        {
            new Book { Title = "Clean Code", Author = "Robert Martin" },
            new Book { Title = "The Pragmatic Programmer", Author = "Dave Thomas" },
            new Book { Title = "Design Patterns: Elements of Reusable Object-Oriented Software", Author = "Erich Gamma" },
        };
        
        var sortedBooks = BooksSorter.Sort(books);
        BooksProcessor.Process(sortedBooks);
    }
}

internal class Book
{
    public String Title { get; set; }
    public String Author { get; set; }
}

internal static class BooksSorter
{
    public static IEnumerable<Book> Sort(IEnumerable<Book> books) 
           => books.OrderBy(book => book.Title);
}

// Imagine this class is actually dozens of classes 
// that all use the concrete Book class...
internal static class BooksProcessor
{
    public static void Process(IEnumerable<Book> books)
    {
        foreach (Book book in books)
            Console.WriteLine(book.Title + " by " + book.Author);
    }
}

My new feature involves adding support for the sorting of videos.

internal class Video
{
    public String Title { get; set; }
    public String Rating { get; set; }
}

Since we already have a class that sorts books by their title, let’s extract an interface and use that instead of the concrete Book class.

internal interface IHasTitle
{
    String Title { get; }
}

internal static class Sorter
{
    public static IEnumerable<IHasTitle> Sort(IEnumerable<IHasTitle> items) => items.OrderBy(item => item.Title);
}

Now we can use the sorter to sort either books or videos. Great! But what about this code?

var sortedBooks = Sorter.Sort(books);
BooksProcessor.Process(sortedBooks);

The BooksProcessor wants concrete Book objects, but our refactoring has changed the sorter’s return type.

Is there a clean way to achieve this reuse without having to cast to a concrete Book object after using the refactored Sorter class?

1

This is solved with generics.

internal static class Sorter
{
    public static IEnumerable<T> Sort(IEnumerable<T> items) where T : IHasTitle
    {
        return items.OrderBy(item => item.Title);
    }
}

By writing it this way, the Sort method will return the same concrete type that was passed in.

Now this code will compile and run fine:

var sortedBooks = Sorter.Sort(books);
BooksProcessor.Process(sortedBooks);

JohnWu’s approach of using templates is fine. Alternatively, instead of avoiding casts at any price, one could encapsulate them at a single place inside the BookSorter class, implemented in terms of a Sorter class:

internal static class BooksSorter
{
    public static IEnumerable<Book> Sort(IEnumerable<Book> books)
    {
         return Sorter.Sort(books).Cast<Book>();
    }
}

Note Sorter.Sort has an implicit contract to return the same objects which where given as input, so this kind of cast isn’t an issue here and unlikely to produce any maintenance issues.

Code which uses the BookSorter class now does not have to worry about the casts any more, and it can stay unchanged.

2

Your Processor should not rely on the concrete type Book to extract Title and Author; instead both books and videos should contain a method self.describe() which differs between concrete classes, so that the Processor need only know that it receives a Describable and not necessarily a Book.

1