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>?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With