What You Don’t Know About Interfaces Can Hurt Your Application

Recently, we’ve discussed the adverse effects that boxing and unboxing can have on the performance of your application. Furthermore, during episode two, we mentioned the unintentional use of boxing when using interfaces and how using generic interfaces instead can help.

But how?

Let’s consider the following example class with my old friend IComparable.

This is a simple class that stores some data, MyData, and provides a comparison method, CompareTo, that will allow it be sorted in a List for example. Notice that this class implements the non-generic IComparable.

Let’s also consider this example class, but notice that it implements the generic version, IComparable<T>.

This class, like MyClass, stores some data, MyData, and provides some comparison operations. But is this just syntactic sugar or are we actual gaining anything?

In short, we’re gaining a lot. Let’s look at an example of each class being used below to see why.

Nothing up our sleeves here, just a simple instance of each class and we’ll compare each to 5. Rather than just trusting the comments to the side, let’s use ILSpy to actually see what’s happening.

Right before the call to MyClass::CompareTo we see that a box operation happens, however, we don’t see that before MyGenericClass::CompareTo.

And if we dig futher with ILSpy into MyClass::CompareTo, we’ll see an unbox operation as a result of our (Int32) casting operation.

But we don’t see an unbox operation in MyGenericClass::CompareTo.

So, in this basic example we can already see that by using generics we can save our applications from calling unnecessary operations. Imagine how much processing time and memory might be used if we were processing large lists of data.

But I mentioned we’d gain a lot. What else have we gained?

Let’s go back to Main and look at the try/catch. With the non-generic version of IComparable we lose type safety at code/compile time. This is a side effect of everything inheriting from Object. Because the String “5″ can safely be cast as an Object, the compiler is OK with this operation. However, our class, MyClass, is not set up to handle this data type. Sure, we’re trapping for it by comparing the type of obj with MyData, but wouldn’t it be nice not to have to worry about it.

This is one of the many benefits that generics provide. Not only do I get to specify which types I want MyGenericClass to support, in this case Int32 and String, but I provide type safety to the users of my class while they are coding/compiling meaning that problems can be presented as compile errors instead of run-time errors which can be more difficult to find. And that can prove invaluable.

Conclusion

In summary, if you have the option to use a generic version of an interface instead of a non-generic version, it’s a no brainer: use the generic version. Not only will you benefit from the better performance within your application but your colleagues will appreciate the ease of use of your classes.

We hope you enjoyed reading this and we’d love to hear your feedback. Drop us a question, comment, or rant at comments@codingblocks.net. Download the examples discussed in this article here.

Share the joy
  •  
  •  
  •  
  •  
  •  
  •  
  •