ListやDictionary、HashSetは名前からしてコレクションに分類されます。
ですから、それぞれ反復処理(例えば、foreachでループ)が出来てほしいですよね。
少なくとも Microsoft の開発者はそう思った訳なので、ListやDictionary、HashSetなどのクラスは全て反復処理が出来るという振る舞いに共通点を持たせることにしました。
それを実現する手段の1つが インターフェース です。
この手段を利用して、反復処理が出来るという共通点をListやDictionary、HashSetなどに持たせるためにIEnumerable<T>インターフェースが作成され、それぞれのクラスに実装されました。
また、反復処理が出来るという共通点を持たせたことで、「反復処理ができるオブジェクトを外部から受け取って、そのオブジェクトなりの反復処理をしてもらいたい」という実装ができるようになりました。
C#
1using System;
2using System.Collections.Generic;
3public class Program
4{
5 public static void Main()
6 {
7 WriteSequence(new[]{1,3,5,7});
8 WriteSequence(new List<string>{"aa","b","cccc"});
9 }
10 public static void WriteSequence<T>(IEnumerable<T> source)
11 {
12 foreach(var element in source)
13 {
14 Console.Write(element);
15 }
16 }
17}
反復処理ができるオブジェクトとは IEnumerable<T> のことです。
WriteSequenceメソッドだけに着目すると何のクラスが外から渡されているかが分かりませんね。それにも関わらず、foreach が実装できて、コンパイルも通り、このプログラムが動作しているのはインターフェースが存在するおかげです。
IEnumerable<T>というインターフェースが存在しなければ、「反復処理ができるオブジェクトを外部から受け取って、そのオブジェクトなりの反復処理をしてもらいたい」という実装ができなくなります。
もちろん、これはIEnumerable<T>に限らず他のインタフェースでも同じことが言えます。
「Xという振る舞いが出来るオブジェクトを外部から受け取って、そのオブジェクトなりのXという振る舞いをしてもらいたい」という実装をするにはインターフェースが必要です。
インターフェースを活用することで、特定のクラスの代わりにインターフェースに依存したコードが生まれます。そのコードを「抽象化されたコード」「抽象に依存したコード」などとよく表現します。
適切なコードの抽象化は読みやすく、修正しやすいコードが生まれますから、「この三つをわざわざ同じように扱えるようにすること」にしたそのメソッド(?)にはそういう意味が込められているかもしれません。
実際にそのコードを拝見している訳ではありませんから、適切に抽象化されているかはわかりません。