Tは単なる型のプレースホルダーです。たとえば、次のようになります。
public void PrintType<T>(T source)
{
    Console.WriteLine(source.GetType());
}
int number = 23;
string text = "Hello";
PrintType(number);
PrintType(text);
ここに、T sourceパラメーターを受け取る汎用関数があります。そのパラメーターの型は何でもかまいません。したがって、Tフラグを立てるために使用します。任意の文字を使用できますが、T最も頻繁に使用されるようです。
List<int>たとえば、一般的なリストがある場合、リストが保持する型を宣言しています。この場合はintegers. これが が必要な理由です<>。ここでタイプを指定します。
List<>ジェネリック型を作成しません。これは、型のオブジェクトを格納できるコレクション オブジェクトです(リストを、などTとして宣言すると仮定します)。内部的には配列を使用していますが、詳細についてはあまり心配する必要はありません。List<T>List<int>List<string>List<>
編集:
List<>参考までに、これは私が使用して取得した単純化された部分的なコードです。dotPeek
public class List<T>
{
    private static readonly T[] _emptyArray = new T[0];
    private const int _defaultCapacity = 4;
    private T[] _items;
    private int _size;
    private int _version;
    public void Add(T item)
    {
      if (this._size == this._items.Length)
        this.EnsureCapacity(this._size + 1);
      this._items[this._size++] = item;
    }
    private void EnsureCapacity(int min)
    {
      if (this._items.Length >= min)
        return;
      int num = this._items.Length == 0 ? 4 : this._items.Length * 2;
      if (num < min)
        num = min;
      this.Capacity = num;
    }
    public int Capacity
    {
      [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] get
      {
        return this._items.Length;
      }
      set
      {
        if (value < this._size)
          ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
        if (value == this._items.Length)
          return;
        if (value > 0)
        {
          T[] objArray = new T[value];
          if (this._size > 0)
            Array.Copy((Array) this._items, 0, (Array) objArray, 0, this._size);
          this._items = objArray;
        }
        else
          this._items = List<T>._emptyArray;
      }
    }
}
ご覧のとおり、List<>は配列 (この場合は汎用配列) を使用するラッパー クラスです。dotPeek または別の同様のツールを入手し、 などを調べてList<>、それらがどのように機能するかをよりよく理解できるようにすることを強くお勧めします。