Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion about Generic type and Lists

Tags:

c#

list

generics

I am learning about generics and Lists in C# but I am very confused with the syntax and the use of the two topics. I have read the MSDN but I am even more confused after reading it.

I am confused how sometimes you can have public T variable name; <-- variable of type T???

Then you can somehow have List<T> or List<double> List<int> <- why do we need the <> all of a sudden and what is this new class called List? If T is a new type different from int or double or string then what values does this new type hold? Why can we put <double>? Are these 2 different concepts? (the List<T> and List<double>) Now they are even using arrays with type T....This type T and List are the 2 things really confusing me. What is the purpose/use of List and how is it different from <T>?

like image 806
Harris Calvin Avatar asked Jan 30 '26 01:01

Harris Calvin


1 Answers

T is simply a placeholder for a type. So for example:

public void PrintType<T>(T source)
{
    Console.WriteLine(source.GetType());
}

int number = 23;
string text = "Hello";

PrintType(number);
PrintType(text);

Here we have a generic function that takes in a T source parameter. The type of that parameter could be anything, thus we use T to flag that. You could use any letter, but T seems most often used.

When you have a generic list List<int> for example, you are declaring the type that the list will hold, in this case integers. This is why you need the <>, it's where you specify the type.

List<> doesn't create a generic type, it is a collection object that can store objects of type T (assuming you declare the list as List<T> e.g. List<int>, List<string>, etc). Under the hood, List<> does use an array, but don't worry too much about the details.

EDIT:

For reference, here is some simplified, partial, code for List<> which I obtained using 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;
      }
    }
}

As you can see, List<> is a wrapper class that uses an array, in this case a generic array. I highly recommend getting dotPeek, or another similar tool, and looking at things like List<>, so you can get a better understanding of how they work.

like image 181
Jason Evans Avatar answered Feb 01 '26 15:02

Jason Evans



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!