Friday, January 4, 2013

Extension methods on Interfaces


Scott Hanselman says every developer should be blogging. So I am going to try and blog and be somewhat consistent.

One interview question I have gotten in the past when interviewing for C# jobs is, "Can an interface implement a method?" At first glance this is a simple question that is meant to determine whether someone has a basic understanding of what an interface is. The answer seems like a 'no', an interface is a contract met by another object that provides the implementations for methods defined by the interface. But here is a better answer, 'yes'. Using extension methods you can attach behavior to an interface and then any class implementing that interface will have access to those methods. Here is a quick example:

public interface IPageableModel
{
int TotalRows { get; }
int PageSize { get; }
}

public static class PageableModelExtensions
{
public static int GetTotalPages(this IPageableModel pageable)
{
return (int)Math.Ceiling((double) (pageable.TotalRows/pageable.PageSize));
}
}

So now anything that implements IPageableModel will also be able to call GetTotalPages. Interfaces have evolved from contracts to attachable behavior. You can now use 'Composition' to give objects behavior instead of 'Inheritance'. Given current thinking that inheritance is a confusing pattern and that it is good to have lots of narrowly defined interfaces attached to objects (Interface Segration Principle of SOLID) , this is a great pattern to use. You can isolate a set of logic into an interface even when that logic doesn't really stand on its own.

Here is another potential usage pattern. One common usage of inheritance is to supply  common services between a set of objects. In web development it is very common to have all of your pages of controllers descend from a common base that you have defined. That way you can essentially share code between all the pages/controllers. But a common problem with this is that your base page/controller is a mess and completely destroys any notion of the S in SOLID (Single Responsibility Principle) because is a a collection of unrelated 'services' to the actual objects. One response would be to divide each set of responsibilities into one layer of inheritance and have all your objects derive from massive chain of object inheritance. This would get pretty confusing pretty fast and would limit flexibility. So a different way to do it would be to just attach  interfaces that contain services to a page or controller. One result is containing all your state in one object. Extension methods can not really hold any state and work on state that the interface requires so any state will necessarily be defined by the object. Personally I don't think this is a bad practice to have all the state for an object defined in one spot while having different chunks of behavior split into interface definitions. I wouldn't say you want to use this pattern to replace all inheritance, but I think it is a good tool to organize your code.

Of course, there is the question of what happens if the actual class already implements the added method, in the example above GetTotalPages. Well then this is used. Note that you don't need override, virtual, or new keywords anywhere in this which is a little dangerous. My code analysis tool, Resharper, also doesn't give me any warnings about this form of overriding which is also bad. Also if you cast the object to the interface you get the interfaces version of the method so both methods are accessible. Another thing is that when you reference an interface extension method inside the object implementing the interface the 'this.' is required before the method. I actually like this particular behavior as it makes it clear that the method isn't defined inside this object, but that it does belong to the object you are in.

So all of this is a little dangerous but fairly flexible, but the key is to not shoot yourself (or the code maintaining your code) in the foot. 

No comments:

Post a Comment