Wednesday, July 11, 2007

a List vs. IList

One of the advantages of being a programming language polyglot is that you get to see the difference of how people work in all those languages. Of course it might take a while before you're comfortable enough with a language to be able to appreciate it, yet step back far enough to see the patterns of people (including yourself) using that language. But once you do, it takes your understanding of programming languages to a whole new level.

That's all very nice and abstract, but I recently encountered a very practical example of the difference between the C# collection classes and the Java collection classes. While reviewing some of the code of a new prodct, I noticed that a lot of methods in the API were accepting and returning List objects.

  • List filterInstructions(List instructions);

Now without reading further tell me, which language is this: C# or Java. Don't worry, I'll wait while you think about it...

Ok, that wasn't very nice of me. You can't really tell which language it is, since the syntax is valid in both.

But there is a huge difference in what it actually means in both languages. In C# List is a concrete implementation of the IList interface. In Java List is an interface, which is implemented by classes like LinkedList and ArrayList. Do you notice the subtle difference? In C# List is a concrete implementation, in Java it is an interface. So the above code sample in C# would accept only instances of the List class (or a subclass), while the Java implementation would accept any implementation of its List interface.

Now I don't want to start a debate on whether classes should accept or return interfaces or concrete classes. There are plenty of good discussions out there. What I want to do is show what might cause the difference in what I often see in Java code and what I see in C# code.

The example above was from a C# class in one of our products. So the developer chose to expose a concrete List implementation, instead of the IList interface. I noticed this and -coming from a Java background- wondered whether our Java developers would normally expose e.g. an ArrayList in Java. They wouldn't. They would expose the List interface instead. So I asked the C# developer why he chose to expose the concrete class, rather than the interface. He didn't have a specific reason, he just did what was easiest: expose the List class.

Keep in mind that a good developer is a lazy developer. So actually this developer was taking the right approach (be lazy) yet he got a different result than what I'm used to seeing in Java code. But then why wouldn't a Java developer expose his ArrayList, but instead choose to expose the List interface?

Well... I know one possible reason. Both of them are exposing the same thing: a list. And actually they are both saying exactly that in their contract: we're accepting and returning a list. It's just that when you literally say that in C# ("I am exposing a List") it translates into a concrete class, while if you say the same thing in Java ("I am exposing a List") it translates into an interface.

It's really all a matter of understanding how a developer thinks and how your choices in class library design influence that thinking. In this case it is very simple: Microsoft seems to put the List class first in your mind, while Sun/Netscape puts the List interface first. A small detail to many, but I found it an interesting difference between the platforms. What a difference an I makes. :-)


Anonymous said...

Coming from a Java background and working with C# now, I noticed the same thing. I thought it was interesting the other day when one of my co-workers asked me why I always use IList instead of List.

Interestingly, he came from a VB background and self-admittedly isn't great with object-oriented design. I wonder if that contributes to the general differences you see between use of languages as well.

Chuck said...

as a C# developer I can tell you most of my implementations return IList or typed IList with the use of Generics. The strongly typed IList< ISomeInterface > at compile time is very useful and lends itself well to IOC and dependency injection patterns.

Marco said...

maybe this boils down to the discussion whether it is a good convention to specifically mark your interfaces, as C# conventionally does by prefixing the "I".

Personally, I find it quite helpful to see that an interface is returned in C# whereas in Java, List could also be a list object / base object.

just my two cents ..

Anonymous said...

There is one good reason to use List in C# rather than IList, which is that IList is completely gimped. There are all sorts of common operations (sort, AddRange, etc.) that are supported by List but not supported by IList. I'd say that is the real flaw in .Net interface.

Anonymous said...

I came from a VB background, and I admit my tendency has been to work with the concrete class rather than the interface.

However now that we have extensions in .NET, it seems more appropriate to extend the interface rather than the concrete class.

I still tend to work with concrete classes when I'm actually working with data though. It just doesn't seem natural to do work with interfaces; interfaces are typically only for using to add meaning at the class/interface level.

Nalin D.Jayasuriya said...

There is another difference when using C# .NET 3.0 and later.

The List (implementation) has the new 'ForEach' Action delegate invocation, while this is lacking in IList.


(I am showing the open square bracket character [ below because the comments section does not allow posting of the less-than character)

private void Test()
List [int> marks = new List[int>() { 0, 1, 2, 3, 4, 5 };


private void PrintMark(int mark)

Anonymous said...

Another reason not to use IList is that you can't really on the types that implement IList.
E.g. think of method that takes an IList as parameter and performs Add() on that parameter. It compiles but if you put in a regular array which implements IList you will get an exception. In C# a lot of types implement IList that really shouldn't. So I never use IList even though I know that exposing interfaces is the way to go.