C# List in ASP.NET – Tutorial for Beginners

In this article, List<T> will be explained in ASP.NET WebForms. ASP.NET will serve as the “output” environment for any “results” of coding. This will be particular useful if you are in the process of learning web development with ASP.NET, which basically you must already been exposed to HTML coding.

Let’s Start

Creates a new project of ASP.NET WebForms, which commonly refers to the project type of

ASP.NET Web Application (.NET Framework)

in Visual Studio.

The following youtube video shows the steps of installing Visual Studio and creating new project of ASP.NET WebForms.

https://www.youtube.com/watch?v=CDcKP3znGv0

Create a new page. Here’s an example of initial ASP.NET front page code:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
        </div>
    </form>
</body>
</html>

Insert a component of PRE block and PlaceHolder into the page:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <pre><asp:PlaceHolder ID="ph1" runat="server"></asp:PlaceHolder></pre>
    </form>
</body>
</html>

Go to code behind

Here’s the initial code of a new page. The C# code demonstrated in the rest of this article will be placed within the main method of Page_Load.

public partial class WebForm1 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
}

List<T> – A list of objects.

The letter “T” in List<T> refers to Object Type.

It can be declared with any object type. For example:

  • string object
  • int object
  • decimal object
  • DateTime object
  • any class object
  • etc…

The Constructors of List<T>

Here are a few ways to create a List<T> in C#.

The default constructor. This creates an empty list.

List<int> lstNo = new List<int>();

Using the List<T>(IEnumerable<T>) constructor. This will pre-populate with an array or an existing list.

<int> lstNo = new List<int> { 1, 2, 3, 4, 5 };

Using the List<T>(int) constructor. This creates a list of integers with a capacity of 10 elements, but no elements are added to the list.

List<int> lstNo = new List<int>(10);

Using the List<T>(int, T) constructor. This creates a list of integers with a capacity of 10 elements and 10 elements with a value of 0.

List<int> lstNo = new List<int>(10, 0);

List<T> is a reference type in C#

When a List<T> object is created and assigned to a variable, the variable becomes a reference to the object. 

Example:

List<int> lstNo = new List<int> { 1, 2, 3, 4, 5 };
List<int> lstA = lstNo;
List<int> lstB = lstA;

These 3 variables of lstNolstA and lstB hold the reference to the same List<int>. If any of the content of the List is modified, the changes will be applied the same to other List. Put it simple, they are the same thing, they holds the same values.

Adding and Getting Values from List<T>

Let’s start with the string object type.

List<string> lst = new List<string>();

Adding string objects into the list.

List<string> lst = new List<string>();
lst.Add("book");
lst.Add("hello");
lst.Add("car");
lst.Add("part");
lst.Add("enter");
lst.Add("forest");
lst.Add("green");

Use the property of Count to get total objects in the List:

lst.Count

Perform a loop to display the content within the List<T>.

  • Foreach Loop
  • For Loop

Using Foreach Loop to Get Values

You can specify the exact object TYPE in the foreach declaration, for example:

foreach (string text in lst)
{ }

Or you can also use the keyword “var” as a generic declaration of implicityly typed local variable, for example:

foreach (var text in lst)
{ }

They both works the same.

Let’s continue, performing foreach loop.

List<string> lst = new List<string>();
lst.Add("book");
lst.Add("hello");
lst.Add("car");
lst.Add("part");
lst.Add("enter");
lst.Add("forest");
lst.Add("green");

StringBuilder sb = new StringBuilder();

sb.AppendLine($"Total objects in List: {lst.Count}");
sb.AppendLine("====================================");

foreach (var text in lst)
{
    sb.AppendLine(text);
}

ph1.Controls.Add(new LiteralControl(sb.ToString()));

Press [F5] or run the website, here’s the output:

Total objects in List: 7
====================================
book
hello
car
part
enter
forest
green

The string can also be combined by using string operation of “+=”. For example:

string output = "";
foreach (var text in lst)
{
    output += text + "<br />";
}

This will also produce the same output, but however, if you are running this in large amount of loops, using the string operation of “+=” will cause a lots of memory usage. String object is immutable. An immutable object is an object that cannot be changed after it has been created. Every time a text is trying to append to it, a new string object is created in memory. This will create a lots of strings in memory. StringBuilder object does not has this problem. It is a specialized string handling object that can be altered and expanded on the go.

Using For Loop to Get Values

for (int i = 0; i < lst.Count; i++)
{
    sb.AppendLine(lst[i]);
}

There are 3 sections in the declaration of a For Loop.

Section 1: declare/set the initial value

int i = 0;

Section 2: set the looping condition

i < lst.Count;

Section 3: set the increment of value or changes of value for each loop

i++

Loop from the 1st data in the List<T>:

StringBuilder sb = new StringBuilder();

sb.AppendLine($"Total objects in List: {lst.Count}");
sb.AppendLine("====================================");

for (int i = 0; i < lst.Count; i++)
{
    sb.AppendLine($"Loop {i}: {lst[i]}");
}

ph1.Controls.Add(new LiteralControl(sb.ToString()));

Press [F5] or run the website, and this will produce the following output:

Total objects in List: 7
====================================
Loop 0: book
Loop 1: hello
Loop 2: car
Loop 3: part
Loop 4: enter
Loop 5: forest
Loop 6: green

Loop from the last data in the List<T>:

for (int i = lst.Count - 1; i >= 0; i--)
{
    sb.AppendLine(lst[i]);
}

Output:

Total objects in List: 7
====================================
Loop 6: green
Loop 5: forest
Loop 4: enter
Loop 3: part
Loop 2: car
Loop 1: hello
Loop 0: book

To get a specific value in List

Get the 1st value:

string output = lst[0];
ph1.Controls.Add(new LiteralControl(output);

Get the 3rd value:

string output = lst[2];
ph1.Controls.Add(new LiteralControl(output);

Let’s do a simple HTML form to play around. Go to the ASP.NET front page, insert the following HTML & controls:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">

        Enter a number:
        <asp:TextBox ID="txtNumber" runat="server" Width="80px"></asp:TextBox>
        <br />
        <br />
        <asp:Button ID="btGetValue" runat="server" Text="Get Value" OnClick="btGetValue_Click" />
        <br />
        <br />
        Output:
        <hr />
        <pre><asp:PlaceHolder ID="ph1" runat="server"></asp:PlaceHolder></pre>

    </form>
</body>
</html>

Go to code behind, the initial code behind will look something like this:

public partial class WebForm1 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
           
    }

    protected void btGetValue_Click(object sender, EventArgs e)
    {

    }
}

In the method of btGetValue_Click, add the following code:

protected void btGetValue_Click(object sender, EventArgs e)
{
    try
    {

    }
    catch (Exception ex)
    {

    }
}

Let’s explains what is the use of “try” and “catch” block code before we continue.

The block of “try” and “catch” are used to capture errors that might occur during real-time operation.

If there is any error occurs in the “try” block, the operation will stop and falls down to the “catch” block. An Exception will be produced (An exception is raised).

The Exception contains the information/description of what kind of error that has been generated. It gives you a clue of how the error is generated.

Let’s try to make an error to see the effect.

First, declare a string object in the “try” block:

try
{
    string aa = "hello";
}
catch (Exception ex)
{
    string err_message = ex.Message;
    ph1.Controls.Add(new LiteralControl(err_message));
}

Then, converts the string into number:

try
{
    string aa = "hello";
    int num = Convert.ToInt32(a);
}
catch (Exception ex)
{
    string err_message = ex.Message;
    ph1.Controls.Add(new LiteralControl(err_message));
}

Display the output to front end:

try
{
    string aa = "hello";
    int num = Convert.ToInt32(a);
    string output = num.ToString();
    ph1.Controls.Add(new LiteralControl(output));
}
catch (Exception ex)
{
    string err_message = ex.Message;
    ph1.Controls.Add(new LiteralControl(err_message));
}

string aa is a text and it’s not a numeric characters. Therefore it can’t be converted into number and this will cause an error. Press [F5] to run the code and the following output will produce:

Input string was not in a correct format.

Let’s change the string aa to numeric characters:

try
{
    string aa = "123";
    int num = Convert.ToInt32(a);
    string output = num.ToString();
    ph1.Controls.Add(new LiteralControl(output));
}
catch (Exception ex)
{
    string err_message = ex.Message;
    ph1.Controls.Add(new LiteralControl(err_message));
}

and this will be the output:

123

Let’s continue. Declare the list of strings:

List<string> lst = new List<string>();
lst.Add("book");
lst.Add("hello");
lst.Add("car");
lst.Add("part");
lst.Add("enter");
lst.Add("forest");
lst.Add("green");

try
{
   
}
catch (Exception ex)
{
    string err_message = ex.Message;
    ph1.Controls.Add(new LiteralControl(err_message));
}

Now, we’ll going to capture the input value from the form submission. The form is considered “submitted” when the user click on the button “btGetValue” which displayed as “Get Value” at user’s web browser.

try
{
    string input = Request.Form["txtNumber"] + "";
}
catch (Exception ex)
{
    string err_message = ex.Message;
    ph1.Controls.Add(new LiteralControl(err_message));
}

Convert the input text into number:

try
{
    string input = Request.Form["txtNumber"] + "";
    int num = Convert.ToInt32(input);
}
catch (Exception ex)
{
    string err_message = ex.Message;
    ph1.Controls.Add(new LiteralControl(err_message));
}

As you can see that the value supplies by user is stored in the form input of “txtNumber” (the textbox). If the user enters non-numeric characters, this will cause the program to encouter error (raise Exception) and crash.

That’s why a “try” & “catch” block is used to prevent the program from crashing and let the program keeps running.

Get the value from the string and displays it to front end:

try
{
    string input = Request.Form["txtNumber"] + "";
    int num = Convert.ToInt32(input);
    string output = lst[num];
    ph1.Controls.Add(new LiteralControl(output));
}
catch (Exception ex)
{
    string err_message = ex.Message;
    ph1.Controls.Add(new LiteralControl(err_message));
}

Press [F5] and run the website.

Getting 5th value:

Getting 7th value:

Getting 100th value:

Invalid input. Not a number.

Process User Input Data Without Using “try” and “catch”

In stead of using “try” & “catch“, use int.TryParse() to test and convert the user input value.

string input = Request.Form["txtNumber"] + "";
int number = 0;

string output = "";

if (int.TryParse(input, out number))
{
    if (number >= lst.Count)
    {
        output = "Index is out of range";
    }
    else
    {
        output = lst[number];
    }
}
else
{
    output = "Invalid input. Please enter numeric value.";
}

ph1.Controls.Add(new LiteralControl(output));

Changing the values in List<T>

To change the values, just reassign new values to the list entries:

StringBuilder sb = new StringBuilder();

List<string> lst = new List<string>();
lst.Add("book");
lst.Add("hello");
lst.Add("car");
lst.Add("part");
lst.Add("enter");
lst.Add("forest");
lst.Add("green");

sb.AppendLine("===============");
sb.AppendLine("Before");
sb.AppendLine("===============");

int count = 0;

foreach (var text in lst)
{
    count++;
    sb.AppendLine($"Item {count}: {text}");
}

lst[0] = "apple";
lst[1] = "orange";
lst[2] = "grape";
lst[3] = "watermelon";
lst[4] = "lemon";
lst[5] = "banana";
lst[6] = "strawberry";

sb.AppendLine();
sb.AppendLine("===============");
sb.AppendLine("After");
sb.AppendLine("===============");

count = 0;

foreach (var text in lst)
{
    count++;
    sb.AppendLine($"Item {count}: {text}");
}

ph1.Controls.Add(new LiteralControl(sb.ToString()));

Output:

===============
Before
===============
Item 1: book
Item 2: hello
Item 3: car
Item 4: part
Item 5: enter
Item 6: forest
Item 7: green

===============
After
===============
Item 1: apple
Item 2: orange
Item 3: grape
Item 4: watermelon
Item 5: lemon
Item 6: banana
Item 7: strawberry

Insert Item into LIST

The Insert syntax has 2 parameters

List.Insert(position, value);

1st parameter will be the position of new item that will be inserted.

2nd parameter is the value.

For example, insert to the 1st position in the List:

lst.Insert(0, "house");

Insert to the 3rd position in the list:

lst.Insert(2, "house");

Remove items from List<T>

Remove the 1st item:

lst.Remove(0);

Remove the 4th item:

lst.Remove(3);

Remove item with exact values:

lst.Remove("car");

To Check The Existence of Value:

if (lst.Contains("book"))
{
    sb.AppendLine("Yes, book exists");
}
else
{
    sb.AppendLine("No, book is not existd")l
}

Example of List<int>

Lets try the List of int object.

List<int> lst = new List<int>();
lst.Add(23);
lst.Add(234);
lst.Add(85);
lst.Add(933);
lst.Add(123);
lst.Add(345);

int total = 0;

foreach(var num in lst)
{
    total += num;
}

string output = total.ToString();

ph1.Controls.Add(new LiteralControl(output));

Output:

1743

Example 2: decimal object

List<decimal> lst = new List<decimal>();
lst.Add(34.234m);
lst.Add(234.88m);
lst.Add(8.15m);
lst.Add(933.66m);
lst.Add(123.1m);
lst.Add(345.09m);

decimal total = 10000m;

foreach (var num in lst)
{
    total -= num;
}

string output = total.ToString();

ph1.Controls.Add(new LiteralControl(output));

Output:

8320.886

Declaring the List of Class Object

Let’s assume that the following class object is created:

class Member
{
    public string Name { get; set; }
    public string Tel { get; set; }
    public string Location { get; set; }
}

Declaring List of Member Object and display the name by using Foreach Loop:

Member m1 = new Member();
m1.Name = "Sam";
m1.Tel = "2938273645";
m1.Location = "New York";

Member m2 = new Member()
{
    Name = "Rose",
    Tel = "9874563789",
    Location = "Los Angelos"
};

Member m3 = new Member();
m3.Name = "Smith";
m3.Tel = "2348734985";
m3.Location = "Jacksonville";

List<Member> lst = new List<Member>();
lst.Add(m1);
lst.Add(m2);
lst.Add(m3);

StringBuilder sb = new StringBuilder();

int count = 0;

foreach (var m in lst)
{
    count++;
    sb.AppendLine($"No. {count}: {m.Name}, Location: {m.Location}");
}

ph1.Controls.Add(new LiteralControl(sb.ToString()));

Output:

No. 1: Sam, Location: New York
No. 2: Rose, Location: Los Angelos
No. 3: Smith, Location: Jacksonville

Let’s build a “Get Members” form that display the HTML table of Members’ Details. Build the ASP.NET front page as follow:

<!DOCTYPEhtml><htmlxmlns="http://www.w3.org/1999/xhtml"><headrunat="server"><title></title><styletype="text/css">table{border-collapse:collapse;}th{padding:10px;color:white;background:#646464;border-right:1pxsolid#a7a7a7;}td{border:1pxsolid#a8a8a8;padding:10px;}tr:nth-child(odd){background:#e6e6e6;}</style></head><body><formid="form1"runat="server"><asp:ButtonID="btGetMembers"runat="server"Text="Get Members"OnClick="btGetMembers_Click"/><hr/><asp:PlaceHolderID="ph1"runat="server"></asp:PlaceHolder></form></body></html>

At the code behind:

protectedvoidbtGetMembers_Click(objectsender,EventArgse){Memberm1=newMember();m1.Name="Sam";m1.Tel="2938273645";m1.Location="New York";Memberm2=newMember(){Name="Rose",Tel="9874563789",Location="Los Angelos"};Memberm3=newMember();m3.Name="Smith";m3.Tel="2348734985";m3.Location="Jacksonville";List<Member>lst=newList<Member>();lst.Add(m1);lst.Add(m2);lst.Add(m3);StringBuildersb=newStringBuilder();sb.Append($@"Total Members:{lst.Count}<br /><br /><table><tr><th>No</th><th>Member's Name</th><th>Tel</th><th>Location</th></tr>");intcount=0;foreach(varminlst){count++;sb.Append($@"<tr><td>{count}</td><td>{m.Name}</td><td>{m.Tel}</td><td>{m.Location}</td></tr>");}sb.Append("</table>");ph1.Controls.Add(newLiteralControl(sb.ToString()));}

The output:

Copying List<T>

Here are some of the common methods to copy a List<T>:

  • List<T>.AddRange
  • List<T>.Concat
  • List<T>.ToArray+List<T>.Add
  • List<T>.GetRange

List<T>.AddRange

Add all elements from another collection (i.e. List or Array) into it’s own.

int[] arrayA={1,2,3,4,5};List<int>lstB=newList<int>{6,7,8,9,};List<int>lstC=newList<int>();// Example 1lstC.AddRange(arrayA);// Example 2lstC.AddRange(lstB);

List<T>.Concat

Combine with another list of elements.

int[] arrayA={1,2,3,4,5};List<int>lstB=newList<int>{6,7,8,9,};List<int>lstC=lstB.Concat(arrayA).ToList();

There seems to have similarities between AddRange and Concat. The main difference between Concat and AddRange is that Concat creates a new sequence that contains the elements of both sequences,while AddRange modifies the original sequence and adds the elements of the other sequence to it.

List<T>.ToArray+List<T>.Add

Convert a list into an array and then add it into another list.

List<int>lstA=newList<int>{6,7,8,9,};// convert list to arrayint[] arrayA=lstA.ToArray();// declare new empty listList<int>lstB=newList<int>();// add the value one by one to the new listforeach(intiinarrayA){lstB.Add(i);}

List<T>.GetRange

Get a range of elements and forms a new list.

List<int>lstA=newList<int>{6,7,8,9,};List<int>lstX=lstA.GetRange(1,4);

In above example, lstX is a new list that has the values from lstA with the elements starting at index 1 to index 4. Translate into English,it means,get all elements start at 2nd position to 5th position in the list.

Sorting the List (Rearrange the List in Specific Orders)

There are many ways to sort a List. This article will introduce 2 methods:

  • Method 1:By using “List<T>.Sort()
  • Method 2:By using “LINQ

Method 1:By using “List<T>.Sort()”

This article will introduce 2 methods:

  • Method 1:By using “List.Sort()
  • Method 2:By using “LINQ

Method 1:By using “List.Sort()”

Sorting a non-class object type list:

// default ascending orderlst.Sort()// default descending orderlst.Reverse();// ascending order-manually comparelst.Sort((x,y)=>x.CompareTo(y));// descending order-manually comparelst.Sort((x,y)=>y.CompareTo(x));

Class object sort by 1 field,i.e. Name (ascending order):

// manually comparelst.Sort((x,y)=>x.Name.CompareTo(y.Name));// using delegatelst.Sort(delegate(Memberx,Membery){returnx.Name.CompareTo(y.Name);});

Sort by 1 element,i.e. Name (descending order):

lst.Sort((x,y)=>y.Name.CompareTo(n.Name));// using delegatelst.Sort(delegate(Memberx,Membery){returny.Name.CompareTo(x.Name);});

Sort by 2 elements,i.e. Name and Location (both ascending order):

lst.Sort(delegate(Memberx,Membery){inta=x.Name.CompareTo(y.Name);if(a==0)a=x.Location.CompareTo(y.Location);returna;});

Method 2:By using “LINQ”

Available common LINQ sorting commands:

  • OrderBy()
  • OrderByDescending()
  • ThenBy()
  • ThenByDescending()

Sort by 1 element,i.e. Name (ascending order):

lst.OrderBy(a=>a.Name);

Sort by 1 element,i.e. Name (descending order):

lst.OrderByDescending(a=>a.Name);

Sort by 2 elements,i.e. Name and Location (both ascending order):

lst.OrderBy(a=>a.Name).ThenBy(a=>a.Location);