List <T>はクラスであり、ICollection <T>およびIEnumerable <T>インターフェイスの両方を実装します。また、ICollection <T>はIEnumerable <T>インターフェイスを拡張します。少なくともすべての観点から、それらは互換性がありません。
List <T>がある場合、このオブジェクトがICollection <T>およびIEnumerable <T>インターフェイスで実装する必要があるメソッドとプロパティを実装することが保証されます。コンパイラはそれを認識しており、ICollection <T>またはIEnumerable <T>に暗黙的にキャストすることが許可されています。ただし、ICollection <T>がある場合は、List <T>か他の何か、おそらくDictionary <T>(TはKeyValuePair)かどうかをコードで明示的にチェックしてから、それをキャストする必要があります欲望。
ICollectionはIEnumerableを拡張しているので、IEnumerableにキャストできます。ただし、IEnumerableのみがある場合は、リストであることは保証されません。かもしれませんが、それは何か他のものである可能性があります。たとえばList <T>をDictionary <T>にキャストしようとすると、無効なキャスト例外が発生します。
したがって、それらは「交換可能」ではありません。
また、多くの汎用インターフェイスがあります。System.Collections.Generic名前空間にあるものを確認してください。
編集:コメントに関して、List <T>またはそれが実装するインターフェイスの1つを使用しても、パフォーマンスの低下はまったくありません。まだ新しいオブジェクトを作成する必要があります。次のコードを確認してください。
List<T> list = new List<T>();
ICollection<T> myColl = list;
IEnumerable<T> myEnum = list;
list、myColl、およびmyEnumはすべて同じオブジェクトを指します。リストとして宣言するか、ICollectionとして宣言するか、IEnumerableとして宣言するかにかかわらず、プログラムでリストを作成する必要があります。私はこれを書くことができました:
ICollection<T> myColl = new List<T>();
myCollは、実行時にはまだリストです。
しかし、これは最も重要なポイントです... 結合を減らし、保守性を高めるために、インターフェイスまたは抽象クラスまたは具象クラスに関係なく、可能な限り最小の分母を使用して変数とメソッドパラメーターを常に宣言する必要があります。
「PerformOperation」メソッドが必要とするのは、要素を列挙し、いくつかの作業を行い、終了することだけであると想像してください。その場合、List <T>で利用できる100以上のメソッドは必要なく、IEnumerable <Tで利用できるものだけが必要です>、したがって、以下が適用されるはずです:
public void PerformOperation(IEnumerable<T> myEnumeration) { ... }
そうすることで、あなたと他の開発者は、IEnumerable <T>インターフェイスを実装するクラスのオブジェクトがこのメソッドに与えられることを知っています。リスト、ディクショナリ、または別の開発者が作成したカスタムコレクションクラスの場合があります。
反対に、具体的なList <T>が明示的に必要であると指定した場合(実際にはめったにないことですが、それでも発生する可能性があります)、あなたと他の開発者は、Listまたは継承する別の具体的なクラスでなければならないことを知っていますリストから。