List<T> leitet von IList<T> ab. Daher könnte die zweite Create Methode nur das Object List<T> als Rückgabewert besitzen, die Erste jedoch alles was von IList<T> ableitet. Wenn Du beides als Liste nutzt wirst Du keinen Unterschied merken. Wenn Du aber auf die Methoden zugreifst, dann wirst Du mehr Methoden bei der List<T> sehen. Hoffe das macht es deutlicher.
Zuerst die Grundlagen: * List<T> ist ein Typ * IList<T> ist ein Interface
Um auf deine Frage zu kommen, wo der unterschied liegt möchte ich das gern an einem Beispiel verdeutlichen:
//soweit bekannt, hier gibt es noch keinen Unterschied. IList<object> myListA = new List<object>(); List<object> myListB = new List<object>();
//aber jetzt IList<object> myListA = new ArrayList(); List<object> myListB = new ArrayList(); //Fehler !!!!
Im zweiten Beispiel geht die erste Zuweisung problemlos durch, die zweite jedoch nicht. Warum? Weil du in der ersten Zeile sagst: "Variable myListA muss ein Object enthalten welches das Interface IList<object> implementiert." In der zweiten Zeile sagst du "Variable myListB muss ein Object vom Typ List<object> sein." (Wobei T für den Typ steht).
Da der Typ ArrayList das Interface IList<T> implementiert funktioniert die erste Zuweisung also.
Auch im ersten Beispiel gibt es schon einen Unterschied: auf myListA lassen sich anschließend nur die Methoden von IList<object> aufrufen, auf myListB jedoch alle von List<object>. Und die Frage war ja gerade, was myListA und myListB voneinander unterscheidet.
Zusätzlich zu dem was oben bereits gesagt wurde, ein paar Erfahrungen:
Wenn du ein "Fan" von Generics-Funktionen und Lambda Expressions wie
myList.ForEach(x => x.Counter++) // kann man nur mit List<T> machen
bist, dann geht das nur mit der Klasse, nicht mit dem Interface.
Für Referenzübergabe (ref / ByRef) kannst du das Interface auch nicht verwenden, wodurch es in Schnittstellendefinition, die über z. B. WCF verwendet werden nicht tauglich ist.
Wie schon gesagt wurde: auf die Methoden von List<T>, und dazu zählt ForEach, kann man nur zugreifen, wenn die Variable als List<T> deklariert wurde. Aber IList<T> erweitert IEnumerable<T>, und damit sind zumindest alle für IEnumerable<T> definierten Erweiterungsmethoden auch für IList<T> gültig, und die haben auch viel mit Generics und Lambda Expressions zu tun.
Für Referenzübergabe muss der Typ genau passen: für "ref List<T>" kann man nur eine als List<T> deklarierte Variable übergeben. Auf "ref IList<T>" hingegen passt nur eine als IList<T> deklarierte Variable.
Wir verwenden WCF als Webservice für eine international verfügbare Rich-Client-Anwendung. Beim Verlassen der Funktion versucht WCF die Ref-Parameter zu instanzieren, das kann bei Übergabe eines Interface-Objektes nicht klappen. Ist unabhängig vom Typ des Interfaces, gilt aber natütrich auch für IList. Vielleicht eine etwas exotische Sicht, aber ich hatte bei der Umstellung die Aufgabe für sämtliche IList und sonstige Parameter zu bereinigen. Das kostet wenn man nicht von Anfang an daran denkt.