Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

C# List in ASP.NET - Tutorial for Beginners

4.00/5 (7 votes)
15 Dec 2022CPOL8 min read 15.7K  
An introduction and demo of using C# List in ASP.NET WebForms
A C# tutorial of List for beginners. The demo is carried out in ASP.NET WebForms.

Image 1

Introduction

This article is about an introduction of using C# List<T> and explained in ASP.NET WebForms environment.

Before 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.

Here is a YouTube video guide for installing Visual Studio and creating new project of ASP.NET WebForms:

The ASP.NET page serves as an "output" to display the result of the coding.

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

ASP.NET
<!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:

ASP.NET
<!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:

Image 2

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

C#
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.

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

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

C#
<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.

C#
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.

C#
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:

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

These 3 variables of lstNo, lstA 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.

The values stored in the List<T> is however have two groups of TYPEs:

Value Type and Reference Type

But anyway, this will be another article for another day. For now, you may refer to [this article] and [this article].

Adding and Getting Values from List<T>

Start with the string object type.

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

Adding string objects into the list.

C#
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 List<T>.Count to get total objects in the List:

C#
lst.Count

Perform a loop to display the content within the List.

  • Foreach loop
  • For loop

Using Foreach Loop to Get Values

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

C#
foreach (string text in lst)
{ }

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

C#
foreach (var text in lst)
{ }

They both works the same.

Let’s continue, performing foreach loop.

C#
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
Note:

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

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

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

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

There are three sections in the declaration of a For loop.

Section 1: Declare/set the initial value:

C#
int i = 0;

Section 2: Set the looping condition:

C#
i < lst.Count;

Section 3: Set the increment of value or changes of value foreach loop:

C#
i++

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

C#
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("====================================");

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>:

C#
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 first value:

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

Get the third value:

C#
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:

ASP.NET
<!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:

C#
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 a "try" and "catch" block code:

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

    }
    catch (Exception ex)
    {

    }
}

Before we continue, let's explains what is the usage of "try" and "catch" block code.

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:

C#
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:

C#
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:

C#
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:

C#
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:

C#
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.

C#
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:

C#
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, 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:

C#
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 the fifth value:

Image 3

Getting the seventh value:

Image 4

Getting the 100th value: (error - there is no 100th value)

Image 5

Entering non-numberic characters: (error - unable to convert into number)

Image 6

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

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

C#
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:

C#
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<T>

The Insert syntax has two parameters:

C#
List.Insert(position, value);

The first parameter will be the position of new item that will be inserted.

The second parameter is the value.

For example, insert to the first position in the List:

C#
lst.Insert(0, "house");

Insert to the third position in the list:

C#
lst.Insert(2, "house");

Remove Items from List<T>

Remove the first item:

C#
lst.Remove(0);

Remove the fourth item:

C#
lst.Remove(3);

Remove item with exact values:

C#
lst.Remove("car");

To Check The Existence of Value

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

Example of List of int/decimal Object

Lets try the List of int object:

C#
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: List of decimal object

C#
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:

C#
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:

C#
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 follows:

ASP.NET
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <style type="text/css">
        table {
            border-collapse: collapse;
        }
        th {
            padding: 10px;
            color: white;
            background: #646464;
            border-right: 1px solid #a7a7a7;
        }
        td {
            border: 1px solid #a8a8a8;
            padding: 10px;
        }
        tr:nth-child(odd){
            background:  #e6e6e6;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">

        <asp:Button ID="btGetMembers" runat="server" Text="Get Members"
                     OnClick="btGetMembers_Click" />
        
        <hr />

        <asp:PlaceHolder ID="ph1" runat="server"></asp:PlaceHolder>

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

At the code behind:

C#
protected void btGetMembers_Click(object sender, EventArgs e)
{
    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();

    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>
");

    int count = 0;

    foreach (var m in lst)
    {
        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(new LiteralControl(sb.ToString()));
}

The output:

Image 7

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.

C#
int[] arrayA = { 1, 2, 3, 4, 5};
List<int> lstB = new List<int> { 6, 7, 8, 9, };
List<int> lstC = new List<int>();

// Example 1
lstC.AddRange(arrayA);

// Example 2
lstC.AddRange(lstB);

List<T>.Concat

Combine with another list of elements.

C#
int[] arrayA = { 1, 2, 3, 4, 5 };
List<int> lstB = new List<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.

C#
List<int> lstA = new List<int> { 6, 7, 8, 9, };

// convert list to array
int[] arrayA = lstA.ToArray();

// declare new empty list
List<int> lstB = new List<int>();

// add the value one by one to the new list
foreach(int i in arrayA)
{
    lstB.Add(i);
}

List<T>.GetRange

Get a range of elements and forms a new list.

C#
List<int> lstA = new List<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 List<T> (Rearrange the List in Specific Orders)

This article will introduce two methods:

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

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

Sorting a non-class object type list:

C#
// default ascending order
lst.Sort()

// default descending order
lst.Reverse();

// ascending order - manually compare
lst.Sort((x, y) => x.CompareTo(y));

// descending order - manually compare
lst.Sort((x, y) => y.CompareTo(x));

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

C#
// manually compare
lst.Sort((x, y) => x.Name.CompareTo(y.Name));

// using delegate
lst.Sort(delegate (Member x, Member y) {
    return x.Name.CompareTo(y.Name);
});

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

C#
lst.Sort((x, y) => y.Name.CompareTo(n.Name));

// using delegate
lst.Sort(delegate (Member x, Member y) {
    return y.Name.CompareTo(x.Name);
});

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

C#
lst.Sort(delegate (Member x, Member y) {
    int a = x.Name.CompareTo(y.Name);
    if (a == 0)
        a = x.Location.CompareTo(y.Location);
    return a;
});

Method 2: By using “LINQ”

Available common LINQ sorting commands:

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

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

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

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

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

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

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

History

  • 16th December, 2022: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)